protected MemoryStream CompressBuffer(byte[] buf, int index, int length) { if (length < MIN_COMPRESS_LENGTH) return null; MemoryStream ms = new MemoryStream(buf.Length); DeflaterOutputStream dos = new DeflaterOutputStream(ms); dos.WriteByte( (byte)(length & 0xff )); dos.WriteByte( (byte)((length >> 8) & 0xff )); dos.WriteByte( (byte)((length >> 16) & 0xff )); dos.WriteByte( 0 ); dos.Write( buf, index, length ); dos.Finish(); if (ms.Length > length+4) return null; return ms; }
/// <summary> /// Creates the static library. /// </summary> /// <param name='dataFile'> /// Data file. /// </param> /// <param name='needZeroEnd'> /// Need zero end. /// </param> public void CreateStaticLibrary(String dataFile, bool needZeroEnd) { // Generate the pretty name this.SymbolName = GetSymbolName (dataFile); // If we need a zero at the end (for text files), add 1 byte int size = (int)new FileInfo (dataFile).Length; byte[] fileBuffer = File.ReadAllBytes (dataFile); this.Logger.LogInfo ("Embedding '" + dataFile + "'..."); // Use raw file this.InputSize = size; byte[] dataBuffer = fileBuffer; if (this.Compress) { // Compress the data file if required using (MemoryStream stream = new MemoryStream()) { using (DeflaterOutputStream deflate = new DeflaterOutputStream(stream)) { int n = 0, len = 0; while (n < size) { len = Math.Min (size - n, CHUNK); deflate.Write (fileBuffer, n, len); n += CHUNK; } if (needZeroEnd) { deflate.WriteByte (0); } deflate.Finish (); } dataBuffer = stream.ToArray (); stream.Close (); } } else if (needZeroEnd) { this.InputSize = size + 1; dataBuffer = new byte[this.InputSize]; Array.Copy(fileBuffer, dataBuffer, size); dataBuffer[size] = 0; } this.OutputSize = dataBuffer.Length; if (this.Compress) { this.Logger.LogInfo ("Compression ratio: " + Math.Floor(100.0 * this.OutputSize / this.InputSize) + "%"); } // Compute the names String sFile = Path.Combine (this.OutputDirectory, this.SymbolName + ".s"); String oFile = Path.Combine (this.OutputDirectory, this.SymbolName + ".o"); String aFile = Path.Combine (this.OutputDirectory, this.SymbolName + ".a"); this.OutputFile = Path.Combine (this.OutputDirectory, "lib" + this.SymbolName + ".a"); // (1) Create the assembly source file this.Logger.LogDebug ("Create assembly file '" + Path.GetFileName (sFile) + "'..."); String content = String.Format (CultureInfo.CurrentCulture, TEMPLATE, this.SymbolName, this.OutputSize, SPACER_BYTE); File.WriteAllText (sFile, content); // (2) Create the object file this.Logger.LogDebug ("Create object file '" + Path.GetFileName (oFile) + "'..."); using (ProcessHelper helper = new ProcessHelper("cc", string.Format("{0} -c -o \"{1}\" \"{2}\"", this.ArchitectureFlags ?? String.Empty, oFile, sFile))) { helper.Logger = this.Logger; helper.Execute (); } // (3) Create the static library this.Logger.LogDebug ("Create library file '" + Path.GetFileName (aFile) + "'..."); using (ProcessHelper helper = new ProcessHelper("libtool", string.Format("-o \"{0}\" \"{1}\"", aFile, oFile))) { helper.Logger = this.Logger; helper.Execute (); } // (4) Swap binary content this.Logger.LogDebug ("Swaping content to '" + Path.GetFileName (this.OutputFile) + "'..."); // Not quite memory-efficient, but simpler to code byte[] outputBuffer = File.ReadAllBytes (aFile); // Search for the beginning and the end of the spacer zone int start = Locate (outputBuffer, new[] {SPACER_BYTE, SPACER_BYTE, SPACER_BYTE, SPACER_BYTE}); // Insert the data file content into the static library Array.Copy (dataBuffer, 0, outputBuffer, start, dataBuffer.Length); // Write the result on the disk File.WriteAllBytes (this.OutputFile, outputBuffer); }