public static async Task <Stream> CreateTemplateStreamAsync([NotNull] ExtendedParseInformation parseOutput, [NotNull] object data, CancellationToken token) { var timeoutCancellation = new CancellationTokenSource(); if (parseOutput.ParserOptions.Timeout != TimeSpan.Zero) { timeoutCancellation.CancelAfter(parseOutput.ParserOptions.Timeout); var anyCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(token, timeoutCancellation.Token); token = anyCancellationToken.Token; } var sourceStream = parseOutput.ParserOptions.SourceFactory(); try { if (!sourceStream.CanWrite) { throw new InvalidOperationException("The stream is ReadOnly"); } using (var byteCounterStreamWriter = new ByteCounterStreamWriter(sourceStream, parseOutput.ParserOptions.Encoding, BufferSize, true)) { var context = new ContextObject(parseOutput.ParserOptions, "") { Value = data, CancellationToken = token }; await parseOutput.InternalTemplate.Value(byteCounterStreamWriter, context); } if (timeoutCancellation.IsCancellationRequested) { sourceStream.Dispose(); throw new TimeoutException($"The requested timeout of {parseOutput.ParserOptions.Timeout:g} for report generation was reached"); } } catch { //If there is any exception while generating the template we must dispose any data written to the stream as it will never returned and might //create a memory leak with this. This is also true for a timeout sourceStream.Dispose(); throw; } return(sourceStream); }
public async Task ExecuteWith(ByteCounterStreamWriter builder, ContextObject context) { foreach (var a in Elements.TakeWhile(e => StopOrAbortBuilding(builder, context))) { if (a is SyncParserAction action) { action(builder, context); } else if (a is AsyncParserAction asyncAction) { await asyncAction(builder, context); } else { throw new InvalidOperationException($"The internal parser action was of a not recognized type '{a.GetType()}'"); } } }
public static Stream CreateTemplateStream([NotNull] ExtendedParseInformation parseOutput, [NotNull] object data, CancellationToken token) { var sourceStream = parseOutput.ParserOptions.SourceFactory(); if (!sourceStream.CanWrite) { throw new InvalidOperationException("The stream is ReadOnly"); } using (var ByteCounterStreamWriter = new ByteCounterStreamWriter(sourceStream, parseOutput.ParserOptions.Encoding, BufferSize, true)) { var context = new ContextObject(parseOutput.ParserOptions) { Value = data, Key = "", CancellationToken = token }; parseOutput.InternalTemplate.Value(ByteCounterStreamWriter, context); } return(sourceStream); }
private static void WriteContent(ByteCounterStreamWriter builder, string content, ContextObject context) { content = content ?? context.Options.Null; var sourceCount = builder.BytesWritten; if (context.Options.MaxSize == 0) { builder.Write(content); return; } if (sourceCount >= context.Options.MaxSize - 1) { builder.ReachedLimit = true; return; } var cl = context.Options.Encoding.GetByteCount(content); var overflow = sourceCount + cl - context.Options.MaxSize; if (overflow <= 0) { //builder.BaseStream.Write(binaryContent, 0, binaryContent.Length); builder.Write(content, cl); return; } if (overflow < content.Length) { builder.Write(content.ToCharArray(0, (int)(cl - overflow)), cl - overflow); } else { builder.Write(content, cl); } }
private static void WriteContent(ByteCounterStreamWriter builder, string content, ContextObject context) { content = content ?? context.Options.Null; var sourceCount = builder.BytesWritten; if (context.Options.MaxSize == 0) { builder.Write(content); return; } if (sourceCount >= context.Options.MaxSize - 1) { builder.ReachedLimit = true; return; } //TODO this is a performance critical operation. As we might deal with variable-length encodings this cannot be compute initial var cl = context.Options.Encoding.GetByteCount(content); var overflow = sourceCount + cl - context.Options.MaxSize; if (overflow <= 0) { builder.Write(content, cl); return; } if (overflow < content.Length) { builder.Write(content.ToCharArray(0, (int)(cl - overflow)), cl - overflow); } else { builder.Write(content, cl); } }
private static bool StopOrAbortBuilding(ByteCounterStreamWriter builder, ContextObject context) { return(!context.AbortGeneration && !context.CancellationToken.IsCancellationRequested && !builder.ReachedLimit); }