Upload 2.0.2
[physicsfs] / lzma / C / Compress / Lzma / LzmaStateTest.c
1 /* 
2 LzmaStateTest.c
3 Test application for LZMA Decoder (State version)
4
5 This file written and distributed to public domain by Igor Pavlov.
6 This file is part of LZMA SDK 4.26 (2005-08-02)
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #include "LzmaStateDecode.h"
14
15 const char *kCantReadMessage = "Can not read input file";
16 const char *kCantWriteMessage = "Can not write output file";
17 const char *kCantAllocateMessage = "Can not allocate memory";
18
19 #define kInBufferSize (1 << 15)
20 #define kOutBufferSize (1 << 15)
21
22 unsigned char g_InBuffer[kInBufferSize];
23 unsigned char g_OutBuffer[kOutBufferSize];
24
25 size_t MyReadFile(FILE *file, void *data, size_t size)
26   { return fread(data, 1, size, file); }
27
28 int MyReadFileAndCheck(FILE *file, void *data, size_t size)
29   { return (MyReadFile(file, data, size) == size); }
30
31 int PrintError(char *buffer, const char *message)
32 {
33   sprintf(buffer + strlen(buffer), "\nError: ");
34   sprintf(buffer + strlen(buffer), message);
35   return 1;
36 }
37
38 int main3(FILE *inFile, FILE *outFile, char *rs)
39 {
40   /* We use two 32-bit integers to construct 64-bit integer for file size.
41      You can remove outSizeHigh, if you don't need >= 4GB supporting,
42      or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
43   UInt32 outSize = 0;
44   UInt32 outSizeHigh = 0; 
45   
46   int waitEOS = 1; 
47   /* waitEOS = 1, if there is no uncompressed size in headers, 
48    so decoder will wait EOS (End of Stream Marker) in compressed stream */
49
50   int i;
51   int res = 0;
52   CLzmaDecoderState state;  /* it's about 140 bytes structure, if int is 32-bit */
53   unsigned char properties[LZMA_PROPERTIES_SIZE];
54   SizeT inAvail = 0;
55   unsigned char *inBuffer = 0;
56
57   if (sizeof(UInt32) < 4)
58     return PrintError(rs, "LZMA decoder needs correct UInt32");
59
60   /* Read LZMA properties for compressed stream */
61
62   if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
63     return PrintError(rs, kCantReadMessage);
64
65   /* Read uncompressed size */
66   
67   for (i = 0; i < 8; i++)
68   {
69     unsigned char b;
70     if (!MyReadFileAndCheck(inFile, &b, 1))
71       return PrintError(rs, kCantReadMessage);
72     if (b != 0xFF)
73       waitEOS = 0;
74     if (i < 4)
75       outSize += (UInt32)(b) << (i * 8);
76     else
77       outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
78   }
79
80   /* Decode LZMA properties and allocate memory */
81   
82   if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
83     return PrintError(rs, "Incorrect stream properties");
84   state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
85   if (state.Probs == 0)
86     return PrintError(rs, kCantAllocateMessage);
87   
88   if (state.Properties.DictionarySize == 0)
89     state.Dictionary = 0;
90   else
91   {
92     state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
93     if (state.Dictionary == 0)
94     {
95       free(state.Probs);
96       return PrintError(rs, kCantAllocateMessage);
97     }
98   }
99   
100   /* Decompress */
101   
102   LzmaDecoderInit(&state);
103   
104   do
105   {
106     SizeT inProcessed, outProcessed;
107     int finishDecoding;
108     UInt32 outAvail = kOutBufferSize;
109     if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
110       outAvail = outSize;
111     if (inAvail == 0)
112     {
113       inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize);
114       inBuffer = g_InBuffer;
115     }
116     finishDecoding = (inAvail == 0);
117     res = LzmaDecode(&state,
118         inBuffer, inAvail, &inProcessed,
119         g_OutBuffer, outAvail, &outProcessed,
120         finishDecoding);
121     if (res != 0)
122     {
123       sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
124       res = 1;
125       break;
126     }
127     inAvail -= inProcessed;
128     inBuffer += inProcessed;
129     
130     if (outFile != 0)  
131       if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed)
132       {
133         PrintError(rs, kCantWriteMessage);
134         res = 1;
135         break;
136       }
137       
138     if (outSize < outProcessed)
139       outSizeHigh--;
140     outSize -= (UInt32)outProcessed;
141     outSize &= 0xFFFFFFFF;
142
143     if (outProcessed == 0 && finishDecoding)
144     {
145       if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
146         res = 1;
147       break;
148     }
149   }
150   while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0  || waitEOS);
151
152   free(state.Dictionary);
153   free(state.Probs);
154   return res;
155 }
156
157 int main2(int numArgs, const char *args[], char *rs)
158 {
159   FILE *inFile = 0;
160   FILE *outFile = 0;
161   int res;
162
163   sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov  2005-08-02\n");
164   if (numArgs < 2 || numArgs > 3)
165   {
166     sprintf(rs + strlen(rs), "\nUsage:  lzmadec file.lzma [outFile]\n");
167     return 1;
168   }
169
170   inFile = fopen(args[1], "rb");
171   if (inFile == 0)
172     return PrintError(rs, "Can not open input file");
173
174   if (numArgs > 2)
175   {
176     outFile = fopen(args[2], "wb+");
177     if (outFile == 0)
178       return PrintError(rs, "Can not open output file");
179   }
180
181   res = main3(inFile, outFile, rs);
182
183   if (outFile != 0)
184     fclose(outFile);
185   fclose(inFile);
186   return res;
187 }
188
189 int main(int numArgs, const char *args[])
190 {
191   char rs[800] = { 0 };
192   int res = main2(numArgs, args, rs);
193   printf(rs);
194   return res;
195 }