Go to the documentation of this file.00001 #include "LzmaFile.h"
00002
00003 #include "LzmaDec.h"
00004 #include "Alloc.h"
00005 #include "Types.h"
00006 #include "7zFile.h"
00007
00008
00009
00010 #include <cmath>
00011 #include <iostream>
00012 #include <queue>
00013 #include <cstdlib>
00014 using namespace std;
00015
00016 const char *kCantReadMessage = "Can not read input file";
00017 const char *kCantWriteMessage = "Can not write output file";
00018 const char *kCantAllocateMessage = "Can not allocate memory";
00019 const char *kDataErrorMessage = "Data error";
00020
00021 static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
00022 static void SzFree(void *p, void *address) { p = p; MyFree(address); }
00023 static ISzAlloc g_Alloc = { SzAlloc, SzFree };
00024
00025 LzmaFile::LzmaFile()
00026 {
00027
00028 fStartNumber = false;
00029
00030 fReadSign = true;
00031 fReadMantisseR = true;
00032 fReadMantisseF = false;
00033 fReadExponentSign = false;
00034 fReadExponent = false;
00035
00036 fNegative = false;
00037 fExponentNegative = false;
00038
00039 fMantisseR = 0;
00040 fMantisseF = 0;
00041 fMantisseFcount = 0;
00042 fExponent = 0;
00043 }
00044
00045
00046 SRes
00047 LzmaFile::Open(const string& fileName)
00048 {
00049
00050
00051
00052 FileSeqInStream_CreateVTable(&inStream);
00053 File_Construct(&inStream.file);
00054
00055 if (InFile_Open(&inStream.file, fileName.c_str()) != 0) {
00056 cout << "Cannot open input file: " << fileName << endl;
00057 cout << "First use: \n\t \'lzma --best " << fileName.substr(0, fileName.rfind(".lzma")) << "\'"
00058 << " to create it. "
00059 << endl;
00060 exit(1);
00061 }
00062
00063 ISeqInStream *stream = &inStream.s;
00064
00065
00066
00067 unsigned char header[LZMA_PROPS_SIZE + 8];
00068 RINOK(SeqInStream_Read(stream, header, sizeof(header)));
00069
00070 unpackSize = 0;
00071 int i = 0;
00072 for (i = 0; i < 8; i++)
00073 unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);
00074
00075 LzmaDec_Construct(&state);
00076 RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));
00077 LzmaDec_Init(&state);
00078
00079 inPos = 0;
00080 inSize = 0;
00081 outPos = 0;
00082 return SZ_OK;
00083 }
00084
00085 SRes
00086 LzmaFile::ReadNextNumber(double& data)
00087 {
00088 if (fStorage.empty()) {
00089 const int ret = DecodeBuffer();
00090 if (ret != SZ_OK) {
00091 cout << "Error in ReadNextNumber ret=" << ret << endl;
00092 return SZ_ERROR_DATA;
00093 }
00094 }
00095
00096 data = fStorage.front();
00097 fStorage.pop();
00098 return SZ_OK;
00099 }
00100
00101
00102
00103 SRes
00104 LzmaFile::FillArray(double* data, const int length)
00105 {
00106 for (int i=0; i<length; ++i) {
00107
00108 if (fStorage.empty()) {
00109 const int ret = DecodeBuffer();
00110 if (ret != SZ_OK) {
00111 cout << "Error in FillArray i=" << i << " ret=" << ret << endl;
00112 return SZ_ERROR_DATA;
00113 }
00114 }
00115
00116 data[i] = fStorage.front();
00117 fStorage.pop();
00118
00119 }
00120
00121 return SZ_OK;
00122
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 SRes
00162 LzmaFile::DecodeBuffer()
00163 {
00164 ISeqInStream *stream = &inStream.s;
00165
00166 const int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
00167
00168
00169 if (inPos == inSize) {
00170 inSize = IN_BUF_SIZE;
00171 RINOK(stream->Read(stream, inBuf, &inSize));
00172 inPos = 0;
00173 }
00174
00175 SizeT inProcessed = inSize - inPos;
00176 SizeT outProcessed = OUT_BUF_SIZE - outPos;
00177 ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
00178 ELzmaStatus status;
00179
00180 if (thereIsSize && outProcessed > unpackSize) {
00181 outProcessed = (SizeT)unpackSize;
00182 finishMode = LZMA_FINISH_END;
00183 }
00184
00185 SRes res = LzmaDec_DecodeToBuf(&state, outBuf, &outProcessed,
00186 inBuf + inPos, &inProcessed, finishMode, &status);
00187 inPos += inProcessed;
00188 unpackSize -= outProcessed;
00189
00190
00191 const char* strBuf = (const char*)outBuf;
00192
00193 int countC = 0;
00194 int countNum = 0;
00195 do {
00196
00197 if (countC >= int(outProcessed)) {
00198
00199
00200
00201 break;
00202 }
00203
00204 const char& C = strBuf[countC];
00205 countC++;
00206
00207
00208
00209 if (C==' ' || C=='\n') {
00210
00211 if (!fStartNumber)
00212 continue;
00213
00214
00215
00216
00217
00218 const double number = (fNegative?-1:1) * (fMantisseR + fMantisseF/pow(10, fMantisseFcount)) * pow(10, (fExponentNegative?-1:1) * fExponent);
00219
00220
00221 fStorage.push(number);
00222 countNum++;
00223
00224 fStartNumber = false;
00225
00226 fReadSign = true;
00227 fReadMantisseR = true;
00228 fReadMantisseF = false;
00229 fReadExponentSign = false;
00230 fReadExponent = false;
00231
00232 fNegative = false;
00233 fExponentNegative = false;
00234
00235 fMantisseR = 0;
00236 fMantisseF = 0;
00237 fMantisseFcount = 0;
00238 fExponent = 0;
00239
00240 continue;
00241 }
00242
00243 fStartNumber = true;
00244 const int num = C - '0';
00245 if (num >= 0 && num <= 9) {
00246
00247 if (fReadMantisseR) {
00248 fReadSign = false;
00249 fMantisseR = fMantisseR*10 + num;
00250 } else if (fReadMantisseF) {
00251 fReadSign = false;
00252 fMantisseF = fMantisseF*10 + num;
00253 ++fMantisseFcount;
00254 } else if (fReadExponent) {
00255 fReadExponentSign = false;
00256 fExponent = fExponent*10 + num;
00257 }
00258
00259 } else {
00260
00261 switch(C) {
00262 case '-':
00263 {
00264 if (fReadSign) {
00265 fNegative = true;
00266 fReadSign = false;
00267 fReadMantisseR = true;
00268 } else if (fReadExponentSign) {
00269 fExponentNegative = true;
00270 fReadExponentSign = false;
00271 fReadExponent = true;
00272 } else {
00273 cout << "LzmaFile: found \'" << C << "\' at wrong position. " << endl;
00274 exit(10);
00275 }
00276 }
00277 break;
00278 case '.':
00279 if (!fReadMantisseR) {
00280 cout << "LzmaFile: found \'" << C << "\' at wrong position. " << endl;
00281 exit(10);
00282 }
00283 fReadMantisseR = false;
00284 fReadMantisseF = true;
00285 break;
00286 case 'e':
00287 case 'E':
00288 case 'D':
00289 case 'd':
00290 if (!fReadMantisseR || !fReadMantisseF) {
00291 fReadMantisseR = false;
00292 fReadMantisseF = false;
00293 fReadExponentSign = true;
00294 fReadExponent = true;
00295 }
00296 break;
00297 default:
00298 cout << "LzmaFile: found \'" << C << "\' at wrong position. " << endl;
00299 exit(10);
00300 break;
00301 }
00302 }
00303
00304 } while(true);
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 if (res != SZ_OK || (thereIsSize && unpackSize == 0))
00324 return res;
00325
00326 if (inProcessed == 0 && outProcessed == 0) {
00327 if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
00328 return SZ_ERROR_DATA;
00329 return res;
00330 }
00331
00332 return SZ_OK;
00333 }
00334
00335
00336
00337
00338 SRes
00339 LzmaFile::DecodeAll()
00340 {
00341 ISeqInStream *stream = &inStream.s;
00342
00343 int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
00344
00345 for (;;) {
00346
00347 if (inPos == inSize) {
00348 inSize = IN_BUF_SIZE;
00349 RINOK(stream->Read(stream, inBuf, &inSize));
00350 inPos = 0;
00351 }
00352
00353 SizeT inProcessed = inSize - inPos;
00354 SizeT outProcessed = OUT_BUF_SIZE - outPos;
00355 ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
00356 ELzmaStatus status;
00357
00358 if (thereIsSize && outProcessed > unpackSize) {
00359 outProcessed = (SizeT)unpackSize;
00360 finishMode = LZMA_FINISH_END;
00361 }
00362
00363 SRes res = LzmaDec_DecodeToBuf(&state, outBuf, &outProcessed,
00364 inBuf + inPos, &inProcessed, finishMode, &status);
00365 inPos += inProcessed;
00366 unpackSize -= outProcessed;
00367
00368
00369 unsigned int k=0;
00370 for (k=0; k<outProcessed; ++k) {
00371 printf("%c", outBuf[k]);
00372 }
00373
00374 if (res != SZ_OK || (thereIsSize && unpackSize == 0))
00375 return res;
00376
00377 if (inProcessed == 0 && outProcessed == 0) {
00378 if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
00379 return SZ_ERROR_DATA;
00380 return res;
00381 }
00382
00383 }
00384
00385 return 0;
00386 }
00387
00388
00389
00390 SRes
00391 LzmaFile::Close()
00392 {
00393 LzmaDec_Free(&state, &g_Alloc);
00394 res = File_Close(&inStream.file);
00395 return res;
00396 }