internal DynamicBoundConfiguration( char valueSeparator, char escapedValueStartAndStop, char escapeValueEscapeChar, RowEndings rowEndings, ReadHeaders readHeader, WriteHeaders writeHeaders, WriteTrailingNewLines writeTrailingNewLine, MemoryPool <char> memoryPool, char?commentChar, int?writeBufferSizeHint, int readBufferSizeHint, IDynamicTypeConverter dynamicTypeConverter, DynamicRowDisposal dynamicRowDisposal ) : base( valueSeparator, escapedValueStartAndStop, escapeValueEscapeChar, rowEndings, readHeader, writeHeaders, writeTrailingNewLine, memoryPool, commentChar, writeBufferSizeHint, readBufferSizeHint, dynamicTypeConverter, dynamicRowDisposal ) { }
internal ConcreteBoundConfiguration( InstanceBuilderDelegate <T> newCons, Column[] deserializeColumns, Column[] serializeColumns, bool[] serializeColumnsNeedEscape, char valueSeparator, char escapedValueStartAndStop, char escapeValueEscapeChar, RowEndings rowEndings, ReadHeaders readHeader, WriteHeaders writeHeaders, WriteTrailingNewLines writeTrailingNewLine, MemoryPool <char> memoryPool, char?commentChar, int?writeBufferSizeHint, int readBufferSizeHint) : base( newCons, deserializeColumns, serializeColumns, serializeColumnsNeedEscape, valueSeparator, escapedValueStartAndStop, escapeValueEscapeChar, rowEndings, readHeader, writeHeaders, writeTrailingNewLine, memoryPool, commentChar, writeBufferSizeHint, readBufferSizeHint ) { }
internal ReaderStateMachine( MemoryPool <char> memoryPool, char escapeStartChar, char valueSeparatorChar, char escapeChar, RowEndings rowEndings, ReadHeaders hasHeaders, char?commentChar ) { RowEndings = rowEndings; HasHeaders = hasHeaders; switch (HasHeaders) { case ReadHeaders.Always: CurrentState = State.Header_Start; break; case ReadHeaders.Never: CurrentState = State.Record_Start; break; default: Throw.InvalidOperationException($"Unexpected {nameof(ReadHeaders)}: {HasHeaders}"); break; } TransitionMatrixHandle = GetTransitionMatrix(RowEndings, escapeStartChar == escapeChar).Pin(); TransitionMatrix = (TransitionRule *)TransitionMatrixHandle.Pointer; SuppressCharLookupDispose = false; (MinimumCharacter, CharLookupOffset, CharLookupOwner, CharLookupPin, CharLookup) = MakeCharacterLookup(memoryPool, escapeStartChar, valueSeparatorChar, escapeChar, commentChar); }
internal ReaderStateMachine( CharacterLookup preAllocLookup, char escapeStartChar, char escapeChar, RowEndings rowEndings, ReadHeaders hasHeaders ) { RowEndings = rowEndings; HasHeaders = hasHeaders; switch (HasHeaders) { case ReadHeaders.Always: CurrentState = State.Header_Start; break; case ReadHeaders.Never: CurrentState = State.Record_Start; break; default: Throw.InvalidOperationException($"Unexpected {nameof(ReadHeaders)}: {HasHeaders}"); break; } TransitionMatrixHandle = GetTransitionMatrix(RowEndings, escapeStartChar == escapeChar).Pin(); TransitionMatrix = (TransitionRule *)TransitionMatrixHandle.Pointer; SuppressCharLookupDispose = true; (MinimumCharacter, CharLookupOffset, _, _, CharLookup) = preAllocLookup; }
/// <summary> /// For working with concrete types. /// </summary> protected BoundConfigurationBase( InstanceBuilderDelegate <T> newCons, Column[] deserializeColumns, Column[] serializeColumns, bool[] serializeColumnsNeedEscape, char valueSeparator, char escapedValueStartAndStop, char escapeValueEscapeChar, RowEndings rowEndings, ReadHeaders readHeader, WriteHeaders writeHeaders, WriteTrailingNewLines writeTrailingNewLine, MemoryPool <char> memoryPool, char?commentChar, int?writeBufferSizeHint, int readBufferSizeHint ) { NewCons = newCons; DeserializeColumns = deserializeColumns; SerializeColumns = serializeColumns; SerializeColumnsNeedEscape = serializeColumnsNeedEscape; ValueSeparator = valueSeparator; ValueSeparatorMemory = ValueSeparator.ToString().AsMemory(); EscapedValueStartAndStop = escapedValueStartAndStop; EscapeValueEscapeChar = escapeValueEscapeChar; RowEnding = rowEndings; WriteBufferSizeHint = writeBufferSizeHint; ReadBufferSizeHint = readBufferSizeHint; switch (RowEnding) { case RowEndings.CarriageReturn: RowEndingMemory = CarriageReturn; break; case RowEndings.CarriageReturnLineFeed: RowEndingMemory = CarriageReturnLineFeed; break; case RowEndings.LineFeed: RowEndingMemory = LineFeed; break; default: // for cases like detecting headers, actually trying to write is NO GOOD... // but construction is fine RowEndingMemory = default; break; } ReadHeader = readHeader; WriteHeader = writeHeaders; WriteTrailingNewLine = writeTrailingNewLine; MemoryPool = memoryPool; CommentChar = commentChar; DynamicTypeConverter = null; }
/// <summary> /// Set the sequence of characters that will end a row. /// </summary> public OptionsBuilder WithRowEnding(RowEndings l) { if (!Enum.IsDefined(Types.RowEndingsType, l)) { Throw.ArgumentException($"Unexpected {nameof(RowEndings)} value: {l}", nameof(l)); } return(WithRowEndingInternal(l)); }
public void Sync(string csv, RowEndings expected) { var config = (ConcreteBoundConfiguration <_Test>)Configuration.For <_Test>(Options.Default.NewBuilder().WithReadHeader(ReadHeaders.None).WithRowEnding(RowEndings.Detect).BuildInternal()); using (var str = new StringReader(csv)) { using (var charLookup = ReaderStateMachine.MakeCharacterLookup(config.MemoryPool, config.EscapedValueStartAndStop, config.ValueSeparator, config.EscapeValueEscapeChar, config.CommentChar)) { var detector = new RowEndingDetector <_Test>(config, charLookup, str); var detect = detector.Detect(); Assert.True(detect.HasValue); Assert.Equal(expected, detect.Value.Ending); } } }
public async Task Async(string csv, RowEndings expected) { var config = (ConcreteBoundConfiguration <_Test>)Configuration.For <_Test>(Options.Default.NewBuilder().WithReadHeader(ReadHeaders.None).WithRowEnding(RowEndings.Detect).BuildInternal()); await RunAsyncReaderVariants <_Foo>( Options.Default, async (_, getReader) => { using (var str = getReader(csv)) { using (var charLookup = ReaderStateMachine.MakeCharacterLookup(config.MemoryPool, config.EscapedValueStartAndStop, config.ValueSeparator, config.EscapeValueEscapeChar, config.CommentChar)) { var detector = new RowEndingDetector <_Test>(config, charLookup, str); var detect = await detector.DetectAsync(CancellationToken.None); Assert.True(detect.HasValue); Assert.Equal(expected, detect.Value.Ending); } } } ); }
// sometimes we want to skip validation in tests internal OptionsBuilder WithRowEndingInternal(RowEndings l) { RowEnding = l; return(this); }
internal ValueTask <(RowEndings Ending, Memory <char> PushBack)?> DetectAsync(CancellationToken cancel) { var continueScan = true; while (continueScan) { var mem = BufferOwner.Memory.Slice(BufferStart, BufferOwner.Memory.Length - BufferStart); var endTask = Inner.ReadAsync(mem, cancel); int end; if (endTask.IsCompletedSuccessfully) { end = endTask.Result; } else { return(DetectAsync_ContinueAfterReadAsync(this, endTask, cancel)); } var buffSpan = BufferOwner.Memory.Span; if (end == 0) { if (BufferStart > 0) { switch (buffSpan[0]) { case '\r': Ending = RowEndings.CarriageReturn; break; case '\n': Ending = RowEndings.LineFeed; break; } } break; } else { AddToPushback(buffSpan.Slice(BufferStart, end)); var len = end + BufferStart; var res = Advance(buffSpan.Slice(0, len)); switch (res) { case AdvanceResult.Continue: BufferStart = 0; continue; case AdvanceResult.Finished: continueScan = false; continue; case AdvanceResult.Continue_PushBackOne: buffSpan[0] = buffSpan[len - 1]; BufferStart = 1; continue; default: return(new ValueTask <(RowEndings Ending, Memory <char> PushBack)?>(default((RowEndings Ending, Memory <char> PushBack)?))); } } } // this implies we're only gonna read a row... so whatever if (Ending == RowEndings.None) { Ending = RowEndings.CarriageReturnLineFeed; } return(new ValueTask <(RowEndings Ending, Memory <char> PushBack)?>((Ending, Pushback.Slice(0, PushbackLength))));