private static RdcBufferPointer GetInputBuffer(Stream source, int inputBufferSize, RdcBufferPointer inputBuffer, ref bool eof) { if (eof) { inputBuffer.Size = 0; inputBuffer.Used = 0; } else { var bytesRead = 0; try { bytesRead = RdcBufferTools.IntPtrCopy(source, inputBuffer.Data, inputBufferSize); } catch (Exception ex) { throw new RdcException("Failed to read from the source stream.", ex); } inputBuffer.Size = (uint)bytesRead; inputBuffer.Used = 0; if (bytesRead < inputBufferSize) { eof = true; } } return(inputBuffer); }
private IList <SignatureInfo> Process(Stream source, IRdcGenerator rdcGenerator, string fileName, ISignatureRepository signatureRepository) { var result = Enumerable.Range(0, _recursionDepth).Reverse().Select(i => new SignatureInfo(i, fileName)).ToList(); var eof = false; var eofOutput = false; // prepare streams var sigStreams = result.Select(item => signatureRepository.CreateContent(item.Name)).ToList(); var inputBuffer = new RdcBufferPointer { Size = 0, Used = 0, Data = Marshal.AllocCoTaskMem(InputBufferSize + 16) }; var rdcBufferPointers = PrepareRdcBufferPointers(); var outputPointers = PrepareOutputPointers(rdcBufferPointers); try { while (!eofOutput) { if (inputBuffer.Size == inputBuffer.Used) { inputBuffer = GetInputBuffer(source, InputBufferSize, inputBuffer, ref eof); } RdcError rdcErrorCode; var hr = rdcGenerator.Process( eof, ref eofOutput, ref inputBuffer, (uint)_recursionDepth, outputPointers, out rdcErrorCode); if (hr != 0) { throw new RdcException("RdcGenerator failed to process the signature block.", hr, rdcErrorCode); } RdcBufferTranslate(outputPointers, rdcBufferPointers); for (var i = 0; i < _recursionDepth; i++) { var resultStream = sigStreams[i]; // Write the signature block to the file. var bytesWritten = RdcBufferTools.IntPtrCopy( rdcBufferPointers[i].Data, resultStream, (int)rdcBufferPointers[i].Used); result[i].Length += bytesWritten; if (rdcBufferPointers[i].Used != bytesWritten) { throw new RdcException("Failed to write to the signature file."); } rdcBufferPointers[i].Used = 0; } RdcBufferTranslate(rdcBufferPointers, outputPointers); } } finally { if (inputBuffer.Data != IntPtr.Zero) { Marshal.FreeCoTaskMem(inputBuffer.Data); } foreach (var item in outputPointers) { Marshal.FreeCoTaskMem(item); } foreach (var item in rdcBufferPointers) { Marshal.FreeCoTaskMem(item.Data); } } result.Reverse(); signatureRepository.Flush(result); return(result); }
public IList <RdcNeed> CreateNeedsList(SignatureInfo seedSignature, SignatureInfo sourceSignature, CancellationToken token) { var result = new List <RdcNeed>(); using (var seedStream = _seedSignatureRepository.GetContentForReading(seedSignature.Name)) using (var sourceStream = _sourceSignatureRepository.GetContentForReading(sourceSignature.Name)) { var fileReader = (IRdcFileReader) new RdcFileReader(seedStream); IRdcComparator comparator; if (_rdcLibrary.CreateComparator(fileReader, ComparatorBufferSize, out comparator) != 0) { throw new RdcException("Cannot create comparator"); } var inputBuffer = new RdcBufferPointer { Size = 0, Used = 0, Data = Marshal.AllocCoTaskMem(InputBufferSize + 16) }; var outputBuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(RdcNeed)) * 256); try { var eofInput = false; var eofOutput = false; var outputPointer = new RdcNeedPointer(); while (!eofOutput) { token.ThrowIfCancellationRequested(); if (inputBuffer.Size == inputBuffer.Used && !eofInput) { var bytesRead = 0; try { bytesRead = RdcBufferTools.IntPtrCopy(sourceStream, inputBuffer.Data, InputBufferSize); } catch (Exception ex) { throw new RdcException("Failed to read from the source stream.", ex); } inputBuffer.Size = (uint)bytesRead; inputBuffer.Used = 0; if (bytesRead < InputBufferSize) { eofInput = true; } } // Initialize our output needs array outputPointer.Size = 256; outputPointer.Used = 0; outputPointer.Data = outputBuffer; RdcError error; var hr = comparator.Process(eofInput, ref eofOutput, ref inputBuffer, ref outputPointer, out error); if (hr != 0) { throw new RdcException("Failed to process the signature block!", hr, error); } // Convert the stream to a Needs array. var needs = GetRdcNeedList(outputPointer); result.AddRange(needs); } } finally { // Free our resources if (outputBuffer != IntPtr.Zero) { Marshal.FreeCoTaskMem(outputBuffer); } if (inputBuffer.Data != IntPtr.Zero) { Marshal.FreeCoTaskMem(inputBuffer.Data); } } return(result); } }