1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync/* Lzma2Dec.c -- LZMA2 Decoder
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync2009-05-03 : Igor Pavlov : Public domain */
3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync/* #define SHOW_DEBUG_INFO */
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifdef SHOW_DEBUG_INFO
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include <stdio.h>
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include <string.h>
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Lzma2Dec.h"
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync/*
15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync00000000  -  EOS
16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync00000001 U U  -  Uncompressed Reset Dic
17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync00000010 U U  -  Uncompressed No Reset
18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync100uuuuu U U P P  -  LZMA no reset
19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync101uuuuu U U P P  -  LZMA reset state
20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync110uuuuu U U P P S  -  LZMA reset state + new prop
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync111uuuuu U U P P S  -  LZMA reset state + new prop + reset dic
22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  u, U - Unpack Size
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  P - Pack Size
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  S - Props
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync*/
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define LZMA2_CONTROL_LZMA (1 << 7)
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define LZMA2_CONTROL_COPY_NO_RESET 2
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define LZMA2_CONTROL_COPY_RESET_DIC 1
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define LZMA2_CONTROL_EOF 0
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define LZMA2_LCLP_MAX 4
39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifdef SHOW_DEBUG_INFO
42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define PRF(x) x
43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#else
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define PRF(x)
45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
47baa3858d3f5d128a5c8466b700098109edcad5f2repo synctypedef enum
48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LZMA2_STATE_CONTROL,
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LZMA2_STATE_UNPACK0,
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LZMA2_STATE_UNPACK1,
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LZMA2_STATE_PACK0,
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LZMA2_STATE_PACK1,
54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LZMA2_STATE_PROP,
55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LZMA2_STATE_DATA,
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LZMA2_STATE_DATA_CONT,
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LZMA2_STATE_FINISHED,
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LZMA2_STATE_ERROR
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} ELzma2State;
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
61baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 dicSize;
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (prop > 40)
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return SZ_ERROR_UNSUPPORTED;
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  props[0] = (Byte)LZMA2_LCLP_MAX;
68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  props[1] = (Byte)(dicSize);
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  props[2] = (Byte)(dicSize >> 8);
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  props[3] = (Byte)(dicSize >> 16);
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  props[4] = (Byte)(dicSize >> 24);
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return SZ_OK;
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
75baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Byte props[LZMA_PROPS_SIZE];
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(Lzma2Dec_GetOldProps(prop, props));
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
82baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Byte props[LZMA_PROPS_SIZE];
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(Lzma2Dec_GetOldProps(prop, props));
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
89baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid Lzma2Dec_Init(CLzma2Dec *p)
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->state = LZMA2_STATE_CONTROL;
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->needInitDic = True;
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->needInitState = True;
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->needInitProp = True;
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LzmaDec_Init(&p->decoder);
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
98baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  switch(p->state)
101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case LZMA2_STATE_CONTROL:
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      p->control = b;
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      PRF(printf("\n %4X ", p->decoder.dicPos));
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      PRF(printf(" %2X", b));
106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (p->control == 0)
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return LZMA2_STATE_FINISHED;
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (LZMA2_IS_UNCOMPRESSED_STATE(p))
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if ((p->control & 0x7F) > 2)
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          return LZMA2_STATE_ERROR;
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        p->unpackSize = 0;
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      else
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return LZMA2_STATE_UNPACK0;
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case LZMA2_STATE_UNPACK0:
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      p->unpackSize |= (UInt32)b << 8;
120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return LZMA2_STATE_UNPACK1;
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case LZMA2_STATE_UNPACK1:
123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      p->unpackSize |= (UInt32)b;
124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      p->unpackSize++;
125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      PRF(printf(" %8d", p->unpackSize));
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case LZMA2_STATE_PACK0:
129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      p->packSize = (UInt32)b << 8;
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return LZMA2_STATE_PACK1;
131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case LZMA2_STATE_PACK1:
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      p->packSize |= (UInt32)b;
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      p->packSize++;
135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      PRF(printf(" %8d", p->packSize));
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case LZMA2_STATE_PROP:
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      int lc, lp;
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (b >= (9 * 5 * 5))
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return LZMA2_STATE_ERROR;
144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      lc = b % 9;
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      b /= 9;
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      p->decoder.prop.pb = b / 5;
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      lp = b % 5;
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (lc + lp > LZMA2_LCLP_MAX)
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return LZMA2_STATE_ERROR;
150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      p->decoder.prop.lc = lc;
151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      p->decoder.prop.lp = lp;
152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      p->needInitProp = False;
153baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return LZMA2_STATE_DATA;
154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return LZMA2_STATE_ERROR;
157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
158baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
159baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
160baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
161baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  memcpy(p->dic + p->dicPos, src, size);
162baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->dicPos += size;
163baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
164baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    p->checkDicSize = p->prop.dicSize;
165baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->processedPos += (UInt32)size;
166baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
167baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
168baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);
169baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
170baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
171baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
172baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
173baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  SizeT inSize = *srcLen;
174baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  *srcLen = 0;
175baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  *status = LZMA_STATUS_NOT_SPECIFIED;
176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
177baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  while (p->state != LZMA2_STATE_FINISHED)
178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    SizeT dicPos = p->decoder.dicPos;
180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (p->state == LZMA2_STATE_ERROR)
181baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return SZ_ERROR_DATA;
182baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
183baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
184baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      *status = LZMA_STATUS_NOT_FINISHED;
185baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return SZ_OK;
186baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
187baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
188baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
189baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (*srcLen == inSize)
190baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
191baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        *status = LZMA_STATUS_NEEDS_MORE_INPUT;
192baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return SZ_OK;
193baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
194baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      (*srcLen)++;
195baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      p->state = Lzma2Dec_UpdateState(p, *src++);
196baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      continue;
197baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
198baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
199baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      SizeT destSizeCur = dicLimit - dicPos;
200baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      SizeT srcSizeCur = inSize - *srcLen;
201baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
202baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
203baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (p->unpackSize <= destSizeCur)
204baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
205baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        destSizeCur = (SizeT)p->unpackSize;
206baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        curFinishMode = LZMA_FINISH_END;
207baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
208baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
209baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (LZMA2_IS_UNCOMPRESSED_STATE(p))
210baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
211baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (*srcLen == inSize)
212baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
213baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          *status = LZMA_STATUS_NEEDS_MORE_INPUT;
214baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          return SZ_OK;
215baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
216baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
217baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (p->state == LZMA2_STATE_DATA)
218baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
219baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
220baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          if (initDic)
221baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            p->needInitProp = p->needInitState = True;
222baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          else if (p->needInitDic)
223baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            return SZ_ERROR_DATA;
224baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          p->needInitDic = False;
225baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          LzmaDec_InitDicAndState(&p->decoder, initDic, False);
226baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
227baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
228baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (srcSizeCur > destSizeCur)
229baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          srcSizeCur = destSizeCur;
230baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
231baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (srcSizeCur == 0)
232baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          return SZ_ERROR_DATA;
233baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
234baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
235baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
236baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        src += srcSizeCur;
237baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        *srcLen += srcSizeCur;
238baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        p->unpackSize -= (UInt32)srcSizeCur;
239baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
240baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
241baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      else
242baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
243baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        SizeT outSizeProcessed;
244baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        SRes res;
245baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
246baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (p->state == LZMA2_STATE_DATA)
247baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
248baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          int mode = LZMA2_GET_LZMA_MODE(p);
249baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          Bool initDic = (mode == 3);
250baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          Bool initState = (mode > 0);
251baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
252baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            return SZ_ERROR_DATA;
253baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
254baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
255baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          p->needInitDic = False;
256baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          p->needInitState = False;
257baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          p->state = LZMA2_STATE_DATA_CONT;
258baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
259baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (srcSizeCur > p->packSize)
260baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          srcSizeCur = (SizeT)p->packSize;
261baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
262baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
263baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
264baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        src += srcSizeCur;
265baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        *srcLen += srcSizeCur;
266baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        p->packSize -= (UInt32)srcSizeCur;
267baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
268baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        outSizeProcessed = p->decoder.dicPos - dicPos;
269baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        p->unpackSize -= (UInt32)outSizeProcessed;
270baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
271baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        RINOK(res);
272baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
273baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          return res;
274baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
275baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (srcSizeCur == 0 && outSizeProcessed == 0)
276baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
277baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
278baa3858d3f5d128a5c8466b700098109edcad5f2repo sync              p->unpackSize != 0 || p->packSize != 0)
279baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            return SZ_ERROR_DATA;
280baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          p->state = LZMA2_STATE_CONTROL;
281baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
282baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
283baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          *status = LZMA_STATUS_NOT_FINISHED;
284baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
285baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
286baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
287baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  *status = LZMA_STATUS_FINISHED_WITH_MARK;
288baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return SZ_OK;
289baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
290baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
291baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
292baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
293baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  SizeT outSize = *destLen, inSize = *srcLen;
294baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  *srcLen = *destLen = 0;
295baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (;;)
296baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
297baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    SizeT srcSizeCur = inSize, outSizeCur, dicPos;
298baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ELzmaFinishMode curFinishMode;
299baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    SRes res;
300baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (p->decoder.dicPos == p->decoder.dicBufSize)
301baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      p->decoder.dicPos = 0;
302baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    dicPos = p->decoder.dicPos;
303baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (outSize > p->decoder.dicBufSize - dicPos)
304baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
305baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      outSizeCur = p->decoder.dicBufSize;
306baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      curFinishMode = LZMA_FINISH_ANY;
307baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
308baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
309baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
310baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      outSizeCur = dicPos + outSize;
311baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      curFinishMode = finishMode;
312baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
313baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
314baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
315baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    src += srcSizeCur;
316baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    inSize -= srcSizeCur;
317baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *srcLen += srcSizeCur;
318baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    outSizeCur = p->decoder.dicPos - dicPos;
319baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
320baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    dest += outSizeCur;
321baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    outSize -= outSizeCur;
322baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *destLen += outSizeCur;
323baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (res != 0)
324baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return res;
325baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (outSizeCur == 0 || outSize == 0)
326baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return SZ_OK;
327baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
328baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
329baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
330baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
331baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
332baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
333baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CLzma2Dec decoder;
334baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  SRes res;
335baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  SizeT outSize = *destLen, inSize = *srcLen;
336baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Byte props[LZMA_PROPS_SIZE];
337baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
338baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Lzma2Dec_Construct(&decoder);
339baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
340baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  *destLen = *srcLen = 0;
341baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  *status = LZMA_STATUS_NOT_SPECIFIED;
342baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  decoder.decoder.dic = dest;
343baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  decoder.decoder.dicBufSize = outSize;
344baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
345baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(Lzma2Dec_GetOldProps(prop, props));
346baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));
347baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
348baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  *srcLen = inSize;
349baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);
350baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  *destLen = decoder.decoder.dicPos;
351baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
352baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    res = SZ_ERROR_INPUT_EOF;
353baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
354baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LzmaDec_FreeProbs(&decoder.decoder, alloc);
355baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return res;
356baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
357