using System; using System.IO; namespace SevenZip { using CommandLineParser; public class CDoubleStream: Stream { public System.IO.Stream s1; public System.IO.Stream s2; public int fileIndex; public long skipSize; public override bool CanRead { get { return true; }} public override bool CanWrite { get { return false; }} public override bool CanSeek { get { return false; }} public override long Length { get { return s1.Length + s2.Length - skipSize; } } public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { int numTotal = 0; while (count > 0) { if (fileIndex == 0) { int num = s1.Read(buffer, offset, count); offset += num; count -= num; numTotal += num; if (num == 0) fileIndex++; } if (fileIndex == 1) { numTotal += s2.Read(buffer, offset, count); return numTotal; } } return numTotal; } public override void Write(byte[] buffer, int offset, int count) { throw (new Exception("can't Write")); } public override long Seek(long offset, System.IO.SeekOrigin origin) { throw (new Exception("can't Seek")); } public override void SetLength(long value) { throw (new Exception("can't SetLength")); } } class LzmaAlone { enum Key { Help1 = 0, Help2, Mode, Dictionary, FastBytes, LitContext, LitPos, PosBits, MatchFinder, EOS, StdIn, StdOut, Train }; static void PrintHelp() { System.Console.WriteLine("\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "<Switches>\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0, 29], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" // + " -si: read data from stdin\n" // + " -so: write data to stdout\n" ); } static bool GetNumber(string s, out Int32 v) { v = 0; for (int i = 0; i < s.Length; i++) { char c = s[i]; if (c < '0' || c > '9') return false; v *= 10; v += (Int32)(c - '0'); } return true; } static int IncorrectCommand() { throw (new Exception("Command line error")); // System.Console.WriteLine("\nCommand line error\n"); // return 1; } static int Main2(string[] args) { System.Console.WriteLine("\nLZMA# 4.61 2008-11-23\n"); if (args.Length == 0) { PrintHelp(); return 0; } SwitchForm[] kSwitchForms = new SwitchForm[13]; int sw = 0; kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("T", SwitchType.UnLimitedPostString, false, 1); Parser parser = new Parser(sw); try { parser.ParseStrings(kSwitchForms, args); } catch { return IncorrectCommand(); } if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs) { PrintHelp(); return 0; } System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Count) return IncorrectCommand(); string command = (string)nonSwitchStrings[paramIndex++]; command = command.ToLower(); bool dictionaryIsDefined = false; Int32 dictionary = 1 << 21; if (parser[(int)Key.Dictionary].ThereIs) { Int32 dicLog; if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog)) IncorrectCommand(); dictionary = (Int32)1 << dicLog; dictionaryIsDefined = true; } string mf = "bt4"; if (parser[(int)Key.MatchFinder].ThereIs) mf = (string)parser[(int)Key.MatchFinder].PostStrings[0]; mf = mf.ToLower(); if (command == "b") { const Int32 kNumDefaultItereations = 10; Int32 numIterations = kNumDefaultItereations; if (paramIndex < nonSwitchStrings.Count) if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations)) numIterations = kNumDefaultItereations; return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary); } string train = ""; if (parser[(int)Key.Train].ThereIs) train = (string)parser[(int)Key.Train].PostStrings[0]; bool encodeMode = false; if (command == "e") encodeMode = true; else if (command == "d") encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[(int)Key.StdIn].ThereIs; bool stdOutMode = parser[(int)Key.StdOut].ThereIs; Stream inStream = null; if (stdInMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string inputName = (string)nonSwitchStrings[paramIndex++]; inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read); } FileStream outStream = null; if (stdOutMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string outputName = (string)nonSwitchStrings[paramIndex++]; outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write); } FileStream trainStream = null; if (train.Length != 0) trainStream = new FileStream(train, FileMode.Open, FileAccess.Read); if (encodeMode) { if (!dictionaryIsDefined) dictionary = 1 << 23; Int32 posStateBits = 2; Int32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data Int32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data Int32 algorithm = 2; Int32 numFastBytes = 128; bool eos = parser[(int)Key.EOS].ThereIs || stdInMode; if (parser[(int)Key.Mode].ThereIs) if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm)) IncorrectCommand(); if (parser[(int)Key.FastBytes].ThereIs) if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes)) IncorrectCommand(); if (parser[(int)Key.LitContext].ThereIs) if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits)) IncorrectCommand(); if (parser[(int)Key.LitPos].ThereIs) if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits)) IncorrectCommand(); if (parser[(int)Key.PosBits].ThereIs) if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits)) IncorrectCommand(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker }; object[] properties = { (Int32)(dictionary), (Int32)(posStateBits), (Int32)(litContextBits), (Int32)(litPosBits), (Int32)(algorithm), (Int32)(numFastBytes), mf, eos }; Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); encoder.SetCoderProperties(propIDs, properties); encoder.WriteCoderProperties(outStream); Int64 fileSize; if (eos || stdInMode) fileSize = -1; else fileSize = inStream.Length; for (int i = 0; i < 8; i++) outStream.WriteByte((Byte)(fileSize >> (8 * i))); if (trainStream != null) { CDoubleStream doubleStream = new CDoubleStream(); doubleStream.s1 = trainStream; doubleStream.s2 = inStream; doubleStream.fileIndex = 0; inStream = doubleStream; long trainFileSize = trainStream.Length; doubleStream.skipSize = 0; if (trainFileSize > dictionary) doubleStream.skipSize = trainFileSize - dictionary; trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin); encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize)); } encoder.Code(inStream, outStream, -1, -1, null); } else if (command == "d") { byte[] properties = new byte[5]; if (inStream.Read(properties, 0, 5) != 5) throw (new Exception("input .lzma is too short")); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); decoder.SetDecoderProperties(properties); if (trainStream != null) { if (!decoder.Train(trainStream)) throw (new Exception("can't train")); } long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.ReadByte(); if (v < 0) throw (new Exception("Can't Read 1")); outSize |= ((long)(byte)v) << (8 * i); } long compressedSize = inStream.Length - inStream.Position; decoder.Code(inStream, outStream, compressedSize, outSize, null); } else throw (new Exception("Command Error")); return 0; } [STAThread] static int Main(string[] args) { try { return Main2(args); } catch (Exception e) { Console.WriteLine("{0} Caught exception #1.", e); // throw e; return 1; } } } }