Upload 2.0.2
[physicsfs] / lzma / CS / 7zip / Compress / LzmaAlone / LzmaAlone.cs
1 using System;
2 using System.IO;
3 namespace SevenZip
4 {
5         using CommandLineParser;
6         
7         public class CDoubleStream: Stream
8         {
9                 public System.IO.Stream s1;
10                 public System.IO.Stream s2;
11                 public int fileIndex;
12                 public long skipSize;
13                 
14                 public override bool CanRead { get { return true; }}
15                 public override bool CanWrite { get { return false; }}
16                 public override bool CanSeek { get { return false; }}
17                 public override long Length { get { return s1.Length + s2.Length - skipSize; } }
18                 public override long Position
19                 {
20                         get { return 0; }
21                         set { }
22                 }
23                 public override void Flush() { }
24                 public override int Read(byte[] buffer, int offset, int count) 
25                 {
26                         int numTotal = 0;
27                         while (count > 0)
28                         {
29                                 if (fileIndex == 0)
30                                 {
31                                         int num = s1.Read(buffer, offset, count);
32                                         offset += num;
33                                         count -= num;
34                                         numTotal += num;
35                                         if (num == 0)
36                                                 fileIndex++;
37                                 }
38                                 if (fileIndex == 1)
39                                 {
40                                         numTotal += s2.Read(buffer, offset, count);
41                                         return numTotal;
42                                 }
43                         }
44                         return numTotal;
45                 }
46                 public override void Write(byte[] buffer, int offset, int count)
47                 {
48                         throw (new Exception("can't Write"));
49                 }
50                 public override long Seek(long offset, System.IO.SeekOrigin origin)
51                 {
52                         throw (new Exception("can't Seek"));
53                 }
54                 public override void SetLength(long value)
55                 {
56                         throw (new Exception("can't SetLength"));
57                 }
58         }
59         
60         class LzmaAlone
61         {
62                 enum Key
63                 {
64                         Help1 = 0,
65                         Help2,
66                         Mode,
67                         Dictionary,
68                         FastBytes,
69                         LitContext,
70                         LitPos,
71                         PosBits,
72                         MatchFinder,
73                         EOS,
74                         StdIn,
75                         StdOut,
76                         Train
77                 };
78
79                 static void PrintHelp()
80                 {
81                         System.Console.WriteLine("\nUsage:  LZMA <e|d> [<switches>...] inputFile outputFile\n" +
82                                 "  e: encode file\n" +
83                                 "  d: decode file\n" +
84                                 "  b: Benchmark\n" +
85                                 "<Switches>\n" +
86                                 // "  -a{N}:  set compression mode - [0, 1], default: 1 (max)\n" +
87                                 "  -d{N}:  set dictionary - [0, 29], default: 23 (8MB)\n" +
88                                 "  -fb{N}: set number of fast bytes - [5, 273], default: 128\n" +
89                                 "  -lc{N}: set number of literal context bits - [0, 8], default: 3\n" +
90                                 "  -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" +
91                                 "  -pb{N}: set number of pos bits - [0, 4], default: 2\n" +
92                                 "  -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" +
93                                 "  -eos:   write End Of Stream marker\n"
94                                 // + "  -si:    read data from stdin\n"
95                                 // + "  -so:    write data to stdout\n"
96                                 );
97                 }
98
99                 static bool GetNumber(string s, out Int32 v)
100                 {
101                         v = 0;
102                         for (int i = 0; i < s.Length; i++)
103                         {
104                                 char c = s[i];
105                                 if (c < '0' || c > '9')
106                                         return false;
107                                 v *= 10;
108                                 v += (Int32)(c - '0');
109                         }
110                         return true;
111                 }
112
113                 static int IncorrectCommand()
114                 {
115                         throw (new Exception("Command line error"));
116                         // System.Console.WriteLine("\nCommand line error\n");
117                         // return 1;
118                 }
119                 static int Main2(string[] args)
120                 {
121                         System.Console.WriteLine("\nLZMA# 4.49 Copyright (c) 1999-2007 Igor Pavlov  2006-07-05\n");
122
123                         if (args.Length == 0)
124                         {
125                                 PrintHelp();
126                                 return 0;
127                         }
128
129                         SwitchForm[] kSwitchForms = new SwitchForm[13];
130                         int sw = 0;
131                         kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false);
132                         kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false);
133                         kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1);
134                         kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1);
135                         kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1);
136                         kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1);
137                         kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1);
138                         kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1);
139                         kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1);
140                         kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false);
141                         kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false);
142                         kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false);
143                         kSwitchForms[sw++] = new SwitchForm("T", SwitchType.UnLimitedPostString, false, 1);
144
145
146                         Parser parser = new Parser(sw);
147                         try
148                         {
149                                 parser.ParseStrings(kSwitchForms, args);
150                         }
151                         catch
152                         {
153                                 return IncorrectCommand();
154                         }
155
156                         if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs)
157                         {
158                                 PrintHelp();
159                                 return 0;
160                         }
161
162                         System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings;
163
164                         int paramIndex = 0;
165                         if (paramIndex >= nonSwitchStrings.Count)
166                                 return IncorrectCommand();
167                         string command = (string)nonSwitchStrings[paramIndex++];
168                         command = command.ToLower();
169
170                         bool dictionaryIsDefined = false;
171                         Int32 dictionary = 1 << 21;
172                         if (parser[(int)Key.Dictionary].ThereIs)
173                         {
174                                 Int32 dicLog;
175                                 if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog))
176                                         IncorrectCommand();
177                                 dictionary = (Int32)1 << dicLog;
178                                 dictionaryIsDefined = true;
179                         }
180                         string mf = "bt4";
181                         if (parser[(int)Key.MatchFinder].ThereIs)
182                                 mf = (string)parser[(int)Key.MatchFinder].PostStrings[0];
183                         mf = mf.ToLower();
184
185                         if (command == "b")
186                         {
187                                 const Int32 kNumDefaultItereations = 10;
188                                 Int32 numIterations = kNumDefaultItereations;
189                                 if (paramIndex < nonSwitchStrings.Count)
190                                         if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations))
191                                                 numIterations = kNumDefaultItereations;
192                                 return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary);
193                         }
194
195                         string train = "";
196                         if (parser[(int)Key.Train].ThereIs)
197                                 train = (string)parser[(int)Key.Train].PostStrings[0];
198
199                         bool encodeMode = false;
200                         if (command == "e")
201                                 encodeMode = true;
202                         else if (command == "d")
203                                 encodeMode = false;
204                         else
205                                 IncorrectCommand();
206
207                         bool stdInMode = parser[(int)Key.StdIn].ThereIs;
208                         bool stdOutMode = parser[(int)Key.StdOut].ThereIs;
209
210                         Stream inStream = null;
211                         if (stdInMode)
212                         {
213                                 throw (new Exception("Not implemeted"));
214                         }
215                         else
216                         {
217                                 if (paramIndex >= nonSwitchStrings.Count)
218                                         IncorrectCommand();
219                                 string inputName = (string)nonSwitchStrings[paramIndex++];
220                                 inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read);
221                         }
222
223                         FileStream outStream = null;
224                         if (stdOutMode)
225                         {
226                                 throw (new Exception("Not implemeted"));
227                         }
228                         else
229                         {
230                                 if (paramIndex >= nonSwitchStrings.Count)
231                                         IncorrectCommand();
232                                 string outputName = (string)nonSwitchStrings[paramIndex++];
233                                 outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write);
234                         }
235
236                         FileStream trainStream = null;
237                         if (train.Length != 0)
238                                 trainStream = new FileStream(train, FileMode.Open, FileAccess.Read);
239
240                         if (encodeMode)
241                         {
242                                 if (!dictionaryIsDefined)
243                                         dictionary = 1 << 23;
244
245                                 Int32 posStateBits = 2;
246                                 Int32 litContextBits = 3; // for normal files
247                                 // UInt32 litContextBits = 0; // for 32-bit data
248                                 Int32 litPosBits = 0;
249                                 // UInt32 litPosBits = 2; // for 32-bit data
250                                 Int32 algorithm = 2;
251                                 Int32 numFastBytes = 128;
252
253                                 bool eos = parser[(int)Key.EOS].ThereIs || stdInMode;
254
255                                 if (parser[(int)Key.Mode].ThereIs)
256                                         if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm))
257                                                 IncorrectCommand();
258
259                                 if (parser[(int)Key.FastBytes].ThereIs)
260                                         if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes))
261                                                 IncorrectCommand();
262                                 if (parser[(int)Key.LitContext].ThereIs)
263                                         if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits))
264                                                 IncorrectCommand();
265                                 if (parser[(int)Key.LitPos].ThereIs)
266                                         if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits))
267                                                 IncorrectCommand();
268                                 if (parser[(int)Key.PosBits].ThereIs)
269                                         if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits))
270                                                 IncorrectCommand();
271
272                                 CoderPropID[] propIDs = 
273                                 {
274                                         CoderPropID.DictionarySize,
275                                         CoderPropID.PosStateBits,
276                                         CoderPropID.LitContextBits,
277                                         CoderPropID.LitPosBits,
278                                         CoderPropID.Algorithm,
279                                         CoderPropID.NumFastBytes,
280                                         CoderPropID.MatchFinder,
281                                         CoderPropID.EndMarker
282                                 };
283                                 object[] properties = 
284                                 {
285                                         (Int32)(dictionary),
286                                         (Int32)(posStateBits),
287                                         (Int32)(litContextBits),
288                                         (Int32)(litPosBits),
289                                         (Int32)(algorithm),
290                                         (Int32)(numFastBytes),
291                                         mf,
292                                         eos
293                                 };
294
295                                 Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder();
296                                 encoder.SetCoderProperties(propIDs, properties);
297                                 encoder.WriteCoderProperties(outStream);
298                                 Int64 fileSize;
299                                 if (eos || stdInMode)
300                                         fileSize = -1;
301                                 else
302                                         fileSize = inStream.Length;
303                                 for (int i = 0; i < 8; i++)
304                                         outStream.WriteByte((Byte)(fileSize >> (8 * i)));
305                                 if (trainStream != null)
306                                 {
307                                         CDoubleStream doubleStream = new CDoubleStream();
308                                         doubleStream.s1 = trainStream;
309                                         doubleStream.s2 = inStream;
310                                         doubleStream.fileIndex = 0;
311                                         inStream = doubleStream;
312                                         long trainFileSize = trainStream.Length;
313                                         doubleStream.skipSize = 0;
314                                         if (trainFileSize > dictionary)
315                                                 doubleStream.skipSize = trainFileSize - dictionary;
316                                         trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin);
317                                         encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize));
318                                 }
319                                 encoder.Code(inStream, outStream, -1, -1, null);
320                         }
321                         else if (command == "d")
322                         {
323                                 byte[] properties = new byte[5];
324                                 if (inStream.Read(properties, 0, 5) != 5)
325                                         throw (new Exception("input .lzma is too short"));
326                                 Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder();
327                                 decoder.SetDecoderProperties(properties);
328                                 if (trainStream != null)
329                                 {
330                                         if (!decoder.Train(trainStream))
331                                                 throw (new Exception("can't train"));
332                                 }
333                                 long outSize = 0;
334                                 for (int i = 0; i < 8; i++)
335                                 {
336                                         int v = inStream.ReadByte();
337                                         if (v < 0)
338                                                 throw (new Exception("Can't Read 1"));
339                                         outSize |= ((long)(byte)v) << (8 * i);
340                                 }
341                                 long compressedSize = inStream.Length - inStream.Position;
342                                 decoder.Code(inStream, outStream, compressedSize, outSize, null);
343                         }
344                         else
345                                 throw (new Exception("Command Error"));
346                         return 0;
347                 }
348
349                 [STAThread]
350                 static int Main(string[] args)
351                 {
352                         try
353                         {
354                                 return Main2(args);
355                         }
356                         catch (Exception e)
357                         {
358                                 Console.WriteLine("{0} Caught exception #1.", e);
359                                 // throw e;
360                                 return 1;
361                         }
362                 }
363         }
364 }