Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:07:30

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   int countNum = 0;
0174   do {
0175     if (countC >= int(outProcessed)) {
0176       // cout << " countC=" << countC
0177       //       << " outProcessed=" << outProcessed
0178       //       << endl;
0179       break;
0180     }
0181 
0182     const char &C = strBuf[countC];
0183     countC++;
0184 
0185     //cout << "\'" << C << "\'" << endl;
0186 
0187     if (C == ' ' || C == '\n') {  // END OF NUMBER
0188 
0189       if (!fStartNumber)
0190         continue;
0191 
0192       //istringstream strToNum(fStrNumber.str().c_str());
0193       //double number = atof(fStrNumber.str().c_str());
0194       //strToNum >> number;
0195 
0196       const double number = (fNegative ? -1 : 1) * (fMantisseR + fMantisseF / pow(10, fMantisseFcount)) *
0197                             pow(10, (fExponentNegative ? -1 : 1) * fExponent);
0198       //cout << " number=" << number << endl;
0199 
0200       fStorage.push(number);
0201       countNum++;
0202 
0203       fStartNumber = false;
0204 
0205       fReadSign = true;
0206       fReadMantisseR = true;
0207       fReadMantisseF = false;
0208       fReadExponentSign = false;
0209       fReadExponent = false;
0210 
0211       fNegative = false;
0212       fExponentNegative = false;
0213 
0214       fMantisseR = 0;
0215       fMantisseF = 0;
0216       fMantisseFcount = 0;
0217       fExponent = 0;
0218 
0219       continue;
0220     }
0221 
0222     fStartNumber = true;
0223     const int num = C - '0';
0224     if (num >= 0 && num <= 9) {
0225       if (fReadMantisseR) {
0226         fReadSign = false;
0227         fMantisseR = fMantisseR * 10 + num;
0228       } else if (fReadMantisseF) {
0229         fReadSign = false;
0230         fMantisseF = fMantisseF * 10 + num;
0231         ++fMantisseFcount;
0232       } else if (fReadExponent) {
0233         fReadExponentSign = false;
0234         fExponent = fExponent * 10 + num;
0235       }
0236 
0237     } else {
0238       switch (C) {
0239         case '-': {
0240           if (fReadSign) {
0241             fNegative = true;
0242             fReadSign = false;
0243             fReadMantisseR = true;
0244           } else if (fReadExponentSign) {
0245             fExponentNegative = true;
0246             fReadExponentSign = false;
0247             fReadExponent = true;
0248           } else {
0249             cout << "LzmaFile: found \'" << C << "\' at wrong position. " << endl;
0250             exit(10);
0251           }
0252         } break;
0253         case '.':
0254           if (!fReadMantisseR) {
0255             cout << "LzmaFile: found \'" << C << "\' at wrong position. " << endl;
0256             exit(10);
0257           }
0258           fReadMantisseR = false;
0259           fReadMantisseF = true;
0260           break;
0261         case 'e':
0262         case 'E':
0263         case 'D':
0264         case 'd':
0265           if (!fReadMantisseR || !fReadMantisseF) {
0266             fReadMantisseR = false;
0267             fReadMantisseF = false;
0268             fReadExponentSign = true;
0269             fReadExponent = true;
0270           }
0271           break;
0272         default:
0273           cout << "LzmaFile: found \'" << C << "\' at wrong position. " << endl;
0274           exit(10);
0275           break;
0276       }
0277     }
0278 
0279   } while (true);
0280 
0281   //strBuf.str("");
0282   //strBuf.clear();
0283 
0284   /*    
0285   if (!strNumber.str().empty()) {
0286     cout << "NACHZUEGLER" << endl;
0287     istringstream strToNum(strNumber.str());
0288     double number;
0289     strToNum >> number;
0290     fStorage.push(number);
0291   }
0292   */
0293 
0294   if (res != SZ_OK || (thereIsSize && unpackSize == 0))
0295     return res;
0296 
0297   if (inProcessed == 0 && outProcessed == 0) {
0298     if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
0299       return SZ_ERROR_DATA;
0300     return res;
0301   }
0302 
0303   return SZ_OK;
0304 }
0305 
0306 SRes LzmaFile::DecodeAll() {
0307   ISeqInStream *stream = &inStream.s;
0308 
0309   int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
0310 
0311   for (;;) {
0312     if (inPos == inSize) {
0313       inSize = IN_BUF_SIZE;
0314       RINOK(stream->Read(stream, inBuf, &inSize));
0315       inPos = 0;
0316     }
0317 
0318     SizeT inProcessed = inSize - inPos;
0319     SizeT outProcessed = OUT_BUF_SIZE - outPos;
0320     ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
0321     ELzmaStatus status;
0322 
0323     if (thereIsSize && outProcessed > unpackSize) {
0324       outProcessed = (SizeT)unpackSize;
0325       finishMode = LZMA_FINISH_END;
0326     }
0327 
0328     SRes res = LzmaDec_DecodeToBuf(&state, outBuf, &outProcessed, inBuf + inPos, &inProcessed, finishMode, &status);
0329     inPos += inProcessed;
0330     unpackSize -= outProcessed;
0331 
0332     unsigned int k = 0;
0333     for (k = 0; k < outProcessed; ++k) {
0334       printf("%c", outBuf[k]);
0335     }
0336 
0337     if (res != SZ_OK || (thereIsSize && unpackSize == 0))
0338       return res;
0339 
0340     if (inProcessed == 0 && outProcessed == 0) {
0341       if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
0342         return SZ_ERROR_DATA;
0343       return res;
0344     }
0345 
0346   }  // for loop
0347 
0348   return 0;
0349 }
0350 
0351 SRes LzmaFile::Close() {
0352   LzmaDec_Free(&state, &g_Alloc);
0353   res = File_Close(&inStream.file);
0354   return res;
0355 }