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
0009
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
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
0046
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
0061
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
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
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
0177
0178
0179 break;
0180 }
0181
0182 const char &C = strBuf[countC];
0183 countC++;
0184
0185
0186
0187 if (C == ' ' || C == '\n') {
0188
0189 if (!fStartNumber)
0190 continue;
0191
0192
0193
0194
0195
0196 const double number = (fNegative ? -1 : 1) * (fMantisseR + fMantisseF / pow(10, fMantisseFcount)) *
0197 pow(10, (fExponentNegative ? -1 : 1) * fExponent);
0198
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
0282
0283
0284
0285
0286
0287
0288
0289
0290
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 }
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 }