all repos — mgba @ 341ebd04356360cfff3e217bf7a419e43b534ef1

mGBA Game Boy Advance Emulator

src/third-party/lzma/Util/Lzma/LzmaUtil.c (view raw)

  1/* LzmaUtil.c -- Test application for LZMA compression
  22014-12-31 : Igor Pavlov : Public domain */
  3
  4#include "../../Precomp.h"
  5
  6#include <stdio.h>
  7#include <stdlib.h>
  8#include <string.h>
  9
 10#include "../../Alloc.h"
 11#include "../../7zFile.h"
 12#include "../../7zVersion.h"
 13#include "../../LzmaDec.h"
 14#include "../../LzmaEnc.h"
 15
 16const char *kCantReadMessage = "Can not read input file";
 17const char *kCantWriteMessage = "Can not write output file";
 18const char *kCantAllocateMessage = "Can not allocate memory";
 19const char *kDataErrorMessage = "Data error";
 20
 21static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
 22static void SzFree(void *p, void *address) { p = p; MyFree(address); }
 23static ISzAlloc g_Alloc = { SzAlloc, SzFree };
 24
 25void PrintHelp(char *buffer)
 26{
 27  strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n"
 28      "\nUsage:  lzma <e|d> inputFile outputFile\n"
 29             "  e: encode file\n"
 30             "  d: decode file\n");
 31}
 32
 33int PrintError(char *buffer, const char *message)
 34{
 35  strcat(buffer, "\nError: ");
 36  strcat(buffer, message);
 37  strcat(buffer, "\n");
 38  return 1;
 39}
 40
 41int PrintErrorNumber(char *buffer, SRes val)
 42{
 43  sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);
 44  return 1;
 45}
 46
 47int PrintUserError(char *buffer)
 48{
 49  return PrintError(buffer, "Incorrect command");
 50}
 51
 52#define IN_BUF_SIZE (1 << 16)
 53#define OUT_BUF_SIZE (1 << 16)
 54
 55static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,
 56    UInt64 unpackSize)
 57{
 58  int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
 59  Byte inBuf[IN_BUF_SIZE];
 60  Byte outBuf[OUT_BUF_SIZE];
 61  size_t inPos = 0, inSize = 0, outPos = 0;
 62  LzmaDec_Init(state);
 63  for (;;)
 64  {
 65    if (inPos == inSize)
 66    {
 67      inSize = IN_BUF_SIZE;
 68      RINOK(inStream->Read(inStream, inBuf, &inSize));
 69      inPos = 0;
 70    }
 71    {
 72      SRes res;
 73      SizeT inProcessed = inSize - inPos;
 74      SizeT outProcessed = OUT_BUF_SIZE - outPos;
 75      ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
 76      ELzmaStatus status;
 77      if (thereIsSize && outProcessed > unpackSize)
 78      {
 79        outProcessed = (SizeT)unpackSize;
 80        finishMode = LZMA_FINISH_END;
 81      }
 82      
 83      res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,
 84        inBuf + inPos, &inProcessed, finishMode, &status);
 85      inPos += inProcessed;
 86      outPos += outProcessed;
 87      unpackSize -= outProcessed;
 88      
 89      if (outStream)
 90        if (outStream->Write(outStream, outBuf, outPos) != outPos)
 91          return SZ_ERROR_WRITE;
 92        
 93      outPos = 0;
 94      
 95      if (res != SZ_OK || (thereIsSize && unpackSize == 0))
 96        return res;
 97      
 98      if (inProcessed == 0 && outProcessed == 0)
 99      {
100        if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
101          return SZ_ERROR_DATA;
102        return res;
103      }
104    }
105  }
106}
107
108static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)
109{
110  UInt64 unpackSize;
111  int i;
112  SRes res = 0;
113
114  CLzmaDec state;
115
116  /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
117  unsigned char header[LZMA_PROPS_SIZE + 8];
118
119  /* Read and parse header */
120
121  RINOK(SeqInStream_Read(inStream, header, sizeof(header)));
122
123  unpackSize = 0;
124  for (i = 0; i < 8; i++)
125    unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);
126
127  LzmaDec_Construct(&state);
128  RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));
129  res = Decode2(&state, outStream, inStream, unpackSize);
130  LzmaDec_Free(&state, &g_Alloc);
131  return res;
132}
133
134static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)
135{
136  CLzmaEncHandle enc;
137  SRes res;
138  CLzmaEncProps props;
139
140  rs = rs;
141
142  enc = LzmaEnc_Create(&g_Alloc);
143  if (enc == 0)
144    return SZ_ERROR_MEM;
145
146  LzmaEncProps_Init(&props);
147  res = LzmaEnc_SetProps(enc, &props);
148
149  if (res == SZ_OK)
150  {
151    Byte header[LZMA_PROPS_SIZE + 8];
152    size_t headerSize = LZMA_PROPS_SIZE;
153    int i;
154
155    res = LzmaEnc_WriteProperties(enc, header, &headerSize);
156    for (i = 0; i < 8; i++)
157      header[headerSize++] = (Byte)(fileSize >> (8 * i));
158    if (outStream->Write(outStream, header, headerSize) != headerSize)
159      res = SZ_ERROR_WRITE;
160    else
161    {
162      if (res == SZ_OK)
163        res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc);
164    }
165  }
166  LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
167  return res;
168}
169
170int main2(int numArgs, const char *args[], char *rs)
171{
172  CFileSeqInStream inStream;
173  CFileOutStream outStream;
174  char c;
175  int res;
176  int encodeMode;
177  Bool useOutFile = False;
178
179  FileSeqInStream_CreateVTable(&inStream);
180  File_Construct(&inStream.file);
181
182  FileOutStream_CreateVTable(&outStream);
183  File_Construct(&outStream.file);
184
185  if (numArgs == 1)
186  {
187    PrintHelp(rs);
188    return 0;
189  }
190
191  if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1)
192    return PrintUserError(rs);
193
194  c = args[1][0];
195  encodeMode = (c == 'e' || c == 'E');
196  if (!encodeMode && c != 'd' && c != 'D')
197    return PrintUserError(rs);
198
199  {
200    size_t t4 = sizeof(UInt32);
201    size_t t8 = sizeof(UInt64);
202    if (t4 != 4 || t8 != 8)
203      return PrintError(rs, "Incorrect UInt32 or UInt64");
204  }
205
206  if (InFile_Open(&inStream.file, args[2]) != 0)
207    return PrintError(rs, "Can not open input file");
208
209  if (numArgs > 3)
210  {
211    useOutFile = True;
212    if (OutFile_Open(&outStream.file, args[3]) != 0)
213      return PrintError(rs, "Can not open output file");
214  }
215  else if (encodeMode)
216    PrintUserError(rs);
217
218  if (encodeMode)
219  {
220    UInt64 fileSize;
221    File_GetLength(&inStream.file, &fileSize);
222    res = Encode(&outStream.s, &inStream.s, fileSize, rs);
223  }
224  else
225  {
226    res = Decode(&outStream.s, useOutFile ? &inStream.s : NULL);
227  }
228
229  if (useOutFile)
230    File_Close(&outStream.file);
231  File_Close(&inStream.file);
232
233  if (res != SZ_OK)
234  {
235    if (res == SZ_ERROR_MEM)
236      return PrintError(rs, kCantAllocateMessage);
237    else if (res == SZ_ERROR_DATA)
238      return PrintError(rs, kDataErrorMessage);
239    else if (res == SZ_ERROR_WRITE)
240      return PrintError(rs, kCantWriteMessage);
241    else if (res == SZ_ERROR_READ)
242      return PrintError(rs, kCantReadMessage);
243    return PrintErrorNumber(rs, res);
244  }
245  return 0;
246}
247
248int MY_CDECL main(int numArgs, const char *args[])
249{
250  char rs[800] = { 0 };
251  int res = main2(numArgs, args, rs);
252  fputs(rs, stdout);
253  return res;
254}