LzmaAlone.cs revision baa3858d3f5d128a5c8466b700098109edcad5f2
1using System; 2using System.IO; 3namespace 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.61 2008-11-23\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} 365