Ejemplo n.º 1
0
        private State Parse(State state, Row row)
        {
            var withQuotesNone = _config.WithQuotes ? 0 : 1;
            var withQuotesInc  = _config.WithQuotes ? 1 : 0;

            while (state != State.end2)
            {
                if (!_currentChunk.MoveNext())
                {
                    var remain = _currentChunk.Count - _currentChunkStart;
                    if (remain > 0)
                    {
                        row.AddColumnData(_currentChunk, _currentChunkStart, remain);
                    }

                    _currentChunk.Dispose();
                    _currentChunk      = null;
                    _currentChunkStart = 0;
                    return(state);
                }
                var part = _currentChunk.Current;

                switch (state)
                {
                case State.start:
                    switch (part.Key)
                    {
                    case Chunk.TypeEnum.quotes:
                        if (row.LastColumnSize > 0)
                        {
                            throw new InvalidDataException($"Data found before quotation marks, at: {_rowCnt}");
                        }
                        _currentChunkStart = part.Value + withQuotesNone;
                        state = State.qdata;
                        break;

                    case Chunk.TypeEnum.comma:
                        row.AddColumnData(_currentChunk, _currentChunkStart, part.Value - _currentChunkStart);
                        row.EndColumnData();
                        _currentChunkStart = part.Value + 1;
                        break;

                    case Chunk.TypeEnum.cr:
                        row.AddColumnData(_currentChunk, _currentChunkStart, part.Value - _currentChunkStart);
                        _currentChunkStart = part.Value + 1;
                        state = State.end1;
                        break;

                    case Chunk.TypeEnum.lf:
                        row.AddColumnData(_currentChunk, _currentChunkStart, part.Value - _currentChunkStart);
                        _currentChunkStart = part.Value + 1;
                        state = State.end2;
                        break;

                    default:
                        throw new InvalidOperationException($"Unexpected operand, at: {_rowCnt}");
                    }
                    break;

                case State.qdata:
                    if (part.Key == Chunk.TypeEnum.quotes)
                    {
                        row.AddColumnData(_currentChunk, _currentChunkStart, part.Value - _currentChunkStart + withQuotesInc);
                        _currentChunkStart = part.Value + 1;
                        state = State.qdatanext;
                    }
                    break;

                case State.qdatanext:
                    if (part.Value - _currentChunkStart != 0)
                    {
                        throw new InvalidDataException($"Unexpected data between quotes, at: {_rowCnt}");
                    }
                    switch (part.Key)
                    {
                    case Chunk.TypeEnum.comma:
                        row.EndColumnData();
                        _currentChunkStart = part.Value + 1;
                        state = State.start;
                        break;

                    case Chunk.TypeEnum.quotes:
                        _currentChunkStart = part.Value;
                        state = State.qdata;
                        break;

                    case Chunk.TypeEnum.cr:
                        _currentChunkStart = part.Value + 1;
                        state = State.end1;
                        break;

                    case Chunk.TypeEnum.lf:
                        _currentChunkStart = part.Value + 1;
                        state = State.end2;
                        break;

                    default:
                        throw new InvalidOperationException($"Unexpected operand, at: {_rowCnt}");
                    }
                    break;

                case State.end1:
                    if (part.Key != Chunk.TypeEnum.lf || (part.Value != 0 && part.Value - _currentChunkStart != 0))
                    {
                        throw new InvalidDataException($"Unexpected data between CRLF, at: {_rowCnt}");
                    }
                    row.EndColumnData();
                    _currentChunkStart = part.Value + 1;
                    state = State.end2;
                    break;

                default:
                    throw new InvalidOperationException($"Unexpected state, at: {_rowCnt}");
                }
            }

            return(state);
        }