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; } }
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.ToInt32() + needSize); } return result; }