private static RdcNeed[] GetRdcNeedList(RdcNeedPointer pointer) { var result = new RdcNeed[pointer.Used]; var ptr = pointer.Data; var needSize = Marshal.SizeOf(typeof(RdcNeed)); // Get our native needs pointer // and deserialize to our managed // RdcNeed array. for (var i = 0; i < result.Length; i++) { result[i] = (RdcNeed)Marshal.PtrToStructure(ptr, typeof(RdcNeed)); // Advance the intermediate pointer // to our next RdcNeed struct. ptr = new IntPtr(ptr.ToInt64() + needSize); } 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); } }