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
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 do {
0174 if (countC >= int(outProcessed)) {
0175
0176
0177
0178 break;
0179 }
0180
0181 const char &C = strBuf[countC];
0182 countC++;
0183
0184
0185
0186 if (C == ' ' || C == '\n') {
0187
0188 if (!fStartNumber)
0189 continue;
0190
0191
0192
0193
0194
0195 const double number = (fNegative ? -1 : 1) * (fMantisseR + fMantisseF / pow(10, fMantisseFcount)) *
0196 pow(10, (fExponentNegative ? -1 : 1) * fExponent);
0197
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
0280
0281
0282
0283
0284
0285
0286
0287
0288
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 }
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 }