1370b324cSopenharmony_ciusing System;
2370b324cSopenharmony_ciusing System.IO;
3370b324cSopenharmony_cinamespace SevenZip
4370b324cSopenharmony_ci{
5370b324cSopenharmony_ci	using CommandLineParser;
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci	public class CDoubleStream: Stream
8370b324cSopenharmony_ci	{
9370b324cSopenharmony_ci		public System.IO.Stream s1;
10370b324cSopenharmony_ci		public System.IO.Stream s2;
11370b324cSopenharmony_ci		public int fileIndex;
12370b324cSopenharmony_ci		public long skipSize;
13370b324cSopenharmony_ci
14370b324cSopenharmony_ci		public override bool CanRead { get { return true; }}
15370b324cSopenharmony_ci		public override bool CanWrite { get { return false; }}
16370b324cSopenharmony_ci		public override bool CanSeek { get { return false; }}
17370b324cSopenharmony_ci		public override long Length { get { return s1.Length + s2.Length - skipSize; } }
18370b324cSopenharmony_ci		public override long Position
19370b324cSopenharmony_ci		{
20370b324cSopenharmony_ci			get { return 0;	}
21370b324cSopenharmony_ci			set { }
22370b324cSopenharmony_ci		}
23370b324cSopenharmony_ci		public override void Flush() { }
24370b324cSopenharmony_ci		public override int Read(byte[] buffer, int offset, int count)
25370b324cSopenharmony_ci		{
26370b324cSopenharmony_ci			int numTotal = 0;
27370b324cSopenharmony_ci			while (count > 0)
28370b324cSopenharmony_ci			{
29370b324cSopenharmony_ci				if (fileIndex == 0)
30370b324cSopenharmony_ci				{
31370b324cSopenharmony_ci					int num = s1.Read(buffer, offset, count);
32370b324cSopenharmony_ci					offset += num;
33370b324cSopenharmony_ci					count -= num;
34370b324cSopenharmony_ci					numTotal += num;
35370b324cSopenharmony_ci					if (num == 0)
36370b324cSopenharmony_ci						fileIndex++;
37370b324cSopenharmony_ci				}
38370b324cSopenharmony_ci				if (fileIndex == 1)
39370b324cSopenharmony_ci				{
40370b324cSopenharmony_ci					numTotal += s2.Read(buffer, offset, count);
41370b324cSopenharmony_ci					return numTotal;
42370b324cSopenharmony_ci				}
43370b324cSopenharmony_ci			}
44370b324cSopenharmony_ci			return numTotal;
45370b324cSopenharmony_ci		}
46370b324cSopenharmony_ci		public override void Write(byte[] buffer, int offset, int count)
47370b324cSopenharmony_ci		{
48370b324cSopenharmony_ci			throw (new Exception("can't Write"));
49370b324cSopenharmony_ci		}
50370b324cSopenharmony_ci		public override long Seek(long offset, System.IO.SeekOrigin origin)
51370b324cSopenharmony_ci		{
52370b324cSopenharmony_ci			throw (new Exception("can't Seek"));
53370b324cSopenharmony_ci		}
54370b324cSopenharmony_ci		public override void SetLength(long value)
55370b324cSopenharmony_ci		{
56370b324cSopenharmony_ci			throw (new Exception("can't SetLength"));
57370b324cSopenharmony_ci		}
58370b324cSopenharmony_ci	}
59370b324cSopenharmony_ci
60370b324cSopenharmony_ci	class LzmaAlone
61370b324cSopenharmony_ci	{
62370b324cSopenharmony_ci		enum Key
63370b324cSopenharmony_ci		{
64370b324cSopenharmony_ci			Help1 = 0,
65370b324cSopenharmony_ci			Help2,
66370b324cSopenharmony_ci			Mode,
67370b324cSopenharmony_ci			Dictionary,
68370b324cSopenharmony_ci			FastBytes,
69370b324cSopenharmony_ci			LitContext,
70370b324cSopenharmony_ci			LitPos,
71370b324cSopenharmony_ci			PosBits,
72370b324cSopenharmony_ci			MatchFinder,
73370b324cSopenharmony_ci			EOS,
74370b324cSopenharmony_ci			StdIn,
75370b324cSopenharmony_ci			StdOut,
76370b324cSopenharmony_ci			Train
77370b324cSopenharmony_ci		};
78370b324cSopenharmony_ci
79370b324cSopenharmony_ci		static void PrintHelp()
80370b324cSopenharmony_ci		{
81370b324cSopenharmony_ci			System.Console.WriteLine("\nUsage:  LZMA <e|d> [<switches>...] inputFile outputFile\n" +
82370b324cSopenharmony_ci				"  e: encode file\n" +
83370b324cSopenharmony_ci				"  d: decode file\n" +
84370b324cSopenharmony_ci				"  b: Benchmark\n" +
85370b324cSopenharmony_ci				"<Switches>\n" +
86370b324cSopenharmony_ci				// "  -a{N}:  set compression mode - [0, 1], default: 1 (max)\n" +
87370b324cSopenharmony_ci				"  -d{N}:  set dictionary - [0, 29], default: 23 (8MB)\n" +
88370b324cSopenharmony_ci				"  -fb{N}: set number of fast bytes - [5, 273], default: 128\n" +
89370b324cSopenharmony_ci				"  -lc{N}: set number of literal context bits - [0, 8], default: 3\n" +
90370b324cSopenharmony_ci				"  -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" +
91370b324cSopenharmony_ci				"  -pb{N}: set number of pos bits - [0, 4], default: 2\n" +
92370b324cSopenharmony_ci				"  -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" +
93370b324cSopenharmony_ci				"  -eos:   write End Of Stream marker\n"
94370b324cSopenharmony_ci				// + "  -si:    read data from stdin\n"
95370b324cSopenharmony_ci				// + "  -so:    write data to stdout\n"
96370b324cSopenharmony_ci				);
97370b324cSopenharmony_ci		}
98370b324cSopenharmony_ci
99370b324cSopenharmony_ci		static bool GetNumber(string s, out Int32 v)
100370b324cSopenharmony_ci		{
101370b324cSopenharmony_ci			v = 0;
102370b324cSopenharmony_ci			for (int i = 0; i < s.Length; i++)
103370b324cSopenharmony_ci			{
104370b324cSopenharmony_ci				char c = s[i];
105370b324cSopenharmony_ci				if (c < '0' || c > '9')
106370b324cSopenharmony_ci					return false;
107370b324cSopenharmony_ci				v *= 10;
108370b324cSopenharmony_ci				v += (Int32)(c - '0');
109370b324cSopenharmony_ci			}
110370b324cSopenharmony_ci			return true;
111370b324cSopenharmony_ci		}
112370b324cSopenharmony_ci
113370b324cSopenharmony_ci		static int IncorrectCommand()
114370b324cSopenharmony_ci		{
115370b324cSopenharmony_ci			throw (new Exception("Command line error"));
116370b324cSopenharmony_ci			// System.Console.WriteLine("\nCommand line error\n");
117370b324cSopenharmony_ci			// return 1;
118370b324cSopenharmony_ci		}
119370b324cSopenharmony_ci		static int Main2(string[] args)
120370b324cSopenharmony_ci		{
121370b324cSopenharmony_ci			System.Console.WriteLine("\nLZMA# 4.61  2008-11-23\n");
122370b324cSopenharmony_ci
123370b324cSopenharmony_ci			if (args.Length == 0)
124370b324cSopenharmony_ci			{
125370b324cSopenharmony_ci				PrintHelp();
126370b324cSopenharmony_ci				return 0;
127370b324cSopenharmony_ci			}
128370b324cSopenharmony_ci
129370b324cSopenharmony_ci			SwitchForm[] kSwitchForms = new SwitchForm[13];
130370b324cSopenharmony_ci			int sw = 0;
131370b324cSopenharmony_ci			kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false);
132370b324cSopenharmony_ci			kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false);
133370b324cSopenharmony_ci			kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1);
134370b324cSopenharmony_ci			kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1);
135370b324cSopenharmony_ci			kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1);
136370b324cSopenharmony_ci			kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1);
137370b324cSopenharmony_ci			kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1);
138370b324cSopenharmony_ci			kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1);
139370b324cSopenharmony_ci			kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1);
140370b324cSopenharmony_ci			kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false);
141370b324cSopenharmony_ci			kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false);
142370b324cSopenharmony_ci			kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false);
143370b324cSopenharmony_ci			kSwitchForms[sw++] = new SwitchForm("T", SwitchType.UnLimitedPostString, false, 1);
144370b324cSopenharmony_ci
145370b324cSopenharmony_ci
146370b324cSopenharmony_ci			Parser parser = new Parser(sw);
147370b324cSopenharmony_ci			try
148370b324cSopenharmony_ci			{
149370b324cSopenharmony_ci				parser.ParseStrings(kSwitchForms, args);
150370b324cSopenharmony_ci			}
151370b324cSopenharmony_ci			catch
152370b324cSopenharmony_ci			{
153370b324cSopenharmony_ci				return IncorrectCommand();
154370b324cSopenharmony_ci			}
155370b324cSopenharmony_ci
156370b324cSopenharmony_ci			if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs)
157370b324cSopenharmony_ci			{
158370b324cSopenharmony_ci				PrintHelp();
159370b324cSopenharmony_ci				return 0;
160370b324cSopenharmony_ci			}
161370b324cSopenharmony_ci
162370b324cSopenharmony_ci			System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings;
163370b324cSopenharmony_ci
164370b324cSopenharmony_ci			int paramIndex = 0;
165370b324cSopenharmony_ci			if (paramIndex >= nonSwitchStrings.Count)
166370b324cSopenharmony_ci				return IncorrectCommand();
167370b324cSopenharmony_ci			string command = (string)nonSwitchStrings[paramIndex++];
168370b324cSopenharmony_ci			command = command.ToLower();
169370b324cSopenharmony_ci
170370b324cSopenharmony_ci			bool dictionaryIsDefined = false;
171370b324cSopenharmony_ci			Int32 dictionary = 1 << 21;
172370b324cSopenharmony_ci			if (parser[(int)Key.Dictionary].ThereIs)
173370b324cSopenharmony_ci			{
174370b324cSopenharmony_ci				Int32 dicLog;
175370b324cSopenharmony_ci				if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog))
176370b324cSopenharmony_ci					IncorrectCommand();
177370b324cSopenharmony_ci				dictionary = (Int32)1 << dicLog;
178370b324cSopenharmony_ci				dictionaryIsDefined = true;
179370b324cSopenharmony_ci			}
180370b324cSopenharmony_ci			string mf = "bt4";
181370b324cSopenharmony_ci			if (parser[(int)Key.MatchFinder].ThereIs)
182370b324cSopenharmony_ci				mf = (string)parser[(int)Key.MatchFinder].PostStrings[0];
183370b324cSopenharmony_ci			mf = mf.ToLower();
184370b324cSopenharmony_ci
185370b324cSopenharmony_ci			if (command == "b")
186370b324cSopenharmony_ci			{
187370b324cSopenharmony_ci				const Int32 kNumDefaultItereations = 10;
188370b324cSopenharmony_ci				Int32 numIterations = kNumDefaultItereations;
189370b324cSopenharmony_ci				if (paramIndex < nonSwitchStrings.Count)
190370b324cSopenharmony_ci					if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations))
191370b324cSopenharmony_ci						numIterations = kNumDefaultItereations;
192370b324cSopenharmony_ci				return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary);
193370b324cSopenharmony_ci			}
194370b324cSopenharmony_ci
195370b324cSopenharmony_ci			string train = "";
196370b324cSopenharmony_ci			if (parser[(int)Key.Train].ThereIs)
197370b324cSopenharmony_ci				train = (string)parser[(int)Key.Train].PostStrings[0];
198370b324cSopenharmony_ci
199370b324cSopenharmony_ci			bool encodeMode = false;
200370b324cSopenharmony_ci			if (command == "e")
201370b324cSopenharmony_ci				encodeMode = true;
202370b324cSopenharmony_ci			else if (command == "d")
203370b324cSopenharmony_ci				encodeMode = false;
204370b324cSopenharmony_ci			else
205370b324cSopenharmony_ci				IncorrectCommand();
206370b324cSopenharmony_ci
207370b324cSopenharmony_ci			bool stdInMode = parser[(int)Key.StdIn].ThereIs;
208370b324cSopenharmony_ci			bool stdOutMode = parser[(int)Key.StdOut].ThereIs;
209370b324cSopenharmony_ci
210370b324cSopenharmony_ci			Stream inStream = null;
211370b324cSopenharmony_ci			if (stdInMode)
212370b324cSopenharmony_ci			{
213370b324cSopenharmony_ci				throw (new Exception("Not implemeted"));
214370b324cSopenharmony_ci			}
215370b324cSopenharmony_ci			else
216370b324cSopenharmony_ci			{
217370b324cSopenharmony_ci				if (paramIndex >= nonSwitchStrings.Count)
218370b324cSopenharmony_ci					IncorrectCommand();
219370b324cSopenharmony_ci				string inputName = (string)nonSwitchStrings[paramIndex++];
220370b324cSopenharmony_ci				inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read);
221370b324cSopenharmony_ci			}
222370b324cSopenharmony_ci
223370b324cSopenharmony_ci			FileStream outStream = null;
224370b324cSopenharmony_ci			if (stdOutMode)
225370b324cSopenharmony_ci			{
226370b324cSopenharmony_ci				throw (new Exception("Not implemeted"));
227370b324cSopenharmony_ci			}
228370b324cSopenharmony_ci			else
229370b324cSopenharmony_ci			{
230370b324cSopenharmony_ci				if (paramIndex >= nonSwitchStrings.Count)
231370b324cSopenharmony_ci					IncorrectCommand();
232370b324cSopenharmony_ci				string outputName = (string)nonSwitchStrings[paramIndex++];
233370b324cSopenharmony_ci				outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write);
234370b324cSopenharmony_ci			}
235370b324cSopenharmony_ci
236370b324cSopenharmony_ci			FileStream trainStream = null;
237370b324cSopenharmony_ci			if (train.Length != 0)
238370b324cSopenharmony_ci				trainStream = new FileStream(train, FileMode.Open, FileAccess.Read);
239370b324cSopenharmony_ci
240370b324cSopenharmony_ci			if (encodeMode)
241370b324cSopenharmony_ci			{
242370b324cSopenharmony_ci				if (!dictionaryIsDefined)
243370b324cSopenharmony_ci					dictionary = 1 << 23;
244370b324cSopenharmony_ci
245370b324cSopenharmony_ci				Int32 posStateBits = 2;
246370b324cSopenharmony_ci				Int32 litContextBits = 3; // for normal files
247370b324cSopenharmony_ci				// UInt32 litContextBits = 0; // for 32-bit data
248370b324cSopenharmony_ci				Int32 litPosBits = 0;
249370b324cSopenharmony_ci				// UInt32 litPosBits = 2; // for 32-bit data
250370b324cSopenharmony_ci				Int32 algorithm = 2;
251370b324cSopenharmony_ci				Int32 numFastBytes = 128;
252370b324cSopenharmony_ci
253370b324cSopenharmony_ci				bool eos = parser[(int)Key.EOS].ThereIs || stdInMode;
254370b324cSopenharmony_ci
255370b324cSopenharmony_ci				if (parser[(int)Key.Mode].ThereIs)
256370b324cSopenharmony_ci					if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm))
257370b324cSopenharmony_ci						IncorrectCommand();
258370b324cSopenharmony_ci
259370b324cSopenharmony_ci				if (parser[(int)Key.FastBytes].ThereIs)
260370b324cSopenharmony_ci					if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes))
261370b324cSopenharmony_ci						IncorrectCommand();
262370b324cSopenharmony_ci				if (parser[(int)Key.LitContext].ThereIs)
263370b324cSopenharmony_ci					if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits))
264370b324cSopenharmony_ci						IncorrectCommand();
265370b324cSopenharmony_ci				if (parser[(int)Key.LitPos].ThereIs)
266370b324cSopenharmony_ci					if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits))
267370b324cSopenharmony_ci						IncorrectCommand();
268370b324cSopenharmony_ci				if (parser[(int)Key.PosBits].ThereIs)
269370b324cSopenharmony_ci					if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits))
270370b324cSopenharmony_ci						IncorrectCommand();
271370b324cSopenharmony_ci
272370b324cSopenharmony_ci				CoderPropID[] propIDs =
273370b324cSopenharmony_ci				{
274370b324cSopenharmony_ci					CoderPropID.DictionarySize,
275370b324cSopenharmony_ci					CoderPropID.PosStateBits,
276370b324cSopenharmony_ci					CoderPropID.LitContextBits,
277370b324cSopenharmony_ci					CoderPropID.LitPosBits,
278370b324cSopenharmony_ci					CoderPropID.Algorithm,
279370b324cSopenharmony_ci					CoderPropID.NumFastBytes,
280370b324cSopenharmony_ci					CoderPropID.MatchFinder,
281370b324cSopenharmony_ci					CoderPropID.EndMarker
282370b324cSopenharmony_ci				};
283370b324cSopenharmony_ci				object[] properties =
284370b324cSopenharmony_ci				{
285370b324cSopenharmony_ci					(Int32)(dictionary),
286370b324cSopenharmony_ci					(Int32)(posStateBits),
287370b324cSopenharmony_ci					(Int32)(litContextBits),
288370b324cSopenharmony_ci					(Int32)(litPosBits),
289370b324cSopenharmony_ci					(Int32)(algorithm),
290370b324cSopenharmony_ci					(Int32)(numFastBytes),
291370b324cSopenharmony_ci					mf,
292370b324cSopenharmony_ci					eos
293370b324cSopenharmony_ci				};
294370b324cSopenharmony_ci
295370b324cSopenharmony_ci				Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder();
296370b324cSopenharmony_ci				encoder.SetCoderProperties(propIDs, properties);
297370b324cSopenharmony_ci				encoder.WriteCoderProperties(outStream);
298370b324cSopenharmony_ci				Int64 fileSize;
299370b324cSopenharmony_ci				if (eos || stdInMode)
300370b324cSopenharmony_ci					fileSize = -1;
301370b324cSopenharmony_ci				else
302370b324cSopenharmony_ci					fileSize = inStream.Length;
303370b324cSopenharmony_ci				for (int i = 0; i < 8; i++)
304370b324cSopenharmony_ci					outStream.WriteByte((Byte)(fileSize >> (8 * i)));
305370b324cSopenharmony_ci				if (trainStream != null)
306370b324cSopenharmony_ci				{
307370b324cSopenharmony_ci					CDoubleStream doubleStream = new CDoubleStream();
308370b324cSopenharmony_ci					doubleStream.s1 = trainStream;
309370b324cSopenharmony_ci					doubleStream.s2 = inStream;
310370b324cSopenharmony_ci					doubleStream.fileIndex = 0;
311370b324cSopenharmony_ci					inStream = doubleStream;
312370b324cSopenharmony_ci					long trainFileSize = trainStream.Length;
313370b324cSopenharmony_ci					doubleStream.skipSize = 0;
314370b324cSopenharmony_ci					if (trainFileSize > dictionary)
315370b324cSopenharmony_ci						doubleStream.skipSize = trainFileSize - dictionary;
316370b324cSopenharmony_ci					trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin);
317370b324cSopenharmony_ci					encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize));
318370b324cSopenharmony_ci				}
319370b324cSopenharmony_ci				encoder.Code(inStream, outStream, -1, -1, null);
320370b324cSopenharmony_ci			}
321370b324cSopenharmony_ci			else if (command == "d")
322370b324cSopenharmony_ci			{
323370b324cSopenharmony_ci				byte[] properties = new byte[5];
324370b324cSopenharmony_ci				if (inStream.Read(properties, 0, 5) != 5)
325370b324cSopenharmony_ci					throw (new Exception("input .lzma is too short"));
326370b324cSopenharmony_ci				Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder();
327370b324cSopenharmony_ci				decoder.SetDecoderProperties(properties);
328370b324cSopenharmony_ci				if (trainStream != null)
329370b324cSopenharmony_ci				{
330370b324cSopenharmony_ci					if (!decoder.Train(trainStream))
331370b324cSopenharmony_ci						throw (new Exception("can't train"));
332370b324cSopenharmony_ci				}
333370b324cSopenharmony_ci				long outSize = 0;
334370b324cSopenharmony_ci				for (int i = 0; i < 8; i++)
335370b324cSopenharmony_ci				{
336370b324cSopenharmony_ci					int v = inStream.ReadByte();
337370b324cSopenharmony_ci					if (v < 0)
338370b324cSopenharmony_ci						throw (new Exception("Can't Read 1"));
339370b324cSopenharmony_ci					outSize |= ((long)(byte)v) << (8 * i);
340370b324cSopenharmony_ci				}
341370b324cSopenharmony_ci				long compressedSize = inStream.Length - inStream.Position;
342370b324cSopenharmony_ci				decoder.Code(inStream, outStream, compressedSize, outSize, null);
343370b324cSopenharmony_ci			}
344370b324cSopenharmony_ci			else
345370b324cSopenharmony_ci				throw (new Exception("Command Error"));
346370b324cSopenharmony_ci			return 0;
347370b324cSopenharmony_ci		}
348370b324cSopenharmony_ci
349370b324cSopenharmony_ci		[STAThread]
350370b324cSopenharmony_ci		static int Main(string[] args)
351370b324cSopenharmony_ci		{
352370b324cSopenharmony_ci			try
353370b324cSopenharmony_ci			{
354370b324cSopenharmony_ci				return Main2(args);
355370b324cSopenharmony_ci			}
356370b324cSopenharmony_ci			catch (Exception e)
357370b324cSopenharmony_ci			{
358370b324cSopenharmony_ci				Console.WriteLine("{0} Caught exception #1.", e);
359370b324cSopenharmony_ci				// throw e;
360370b324cSopenharmony_ci				return 1;
361370b324cSopenharmony_ci			}
362370b324cSopenharmony_ci		}
363370b324cSopenharmony_ci	}
364370b324cSopenharmony_ci}
365