Exemplo n.º 1
0
        private static string[] ParseCsv(TextReader reader, ref int lineNum, char separator)
        {
            var curChar = CharReader.Create(reader);

            if (curChar.IsEof)
            {
                return(null);                // EOF reached
            }
            if (curChar.IsEol)
            {
                lineNum++;
#if !FW452
                return(Array.Empty <string>());
#else
                return(Array <string> .Empty);
#endif
            }

            var           result   = new List <string>();
            StringBuilder curField = null;
            var           state    = ParserState.ExpectField;
            var           column   = 1;
            while (true)
            {
                var skip = false;

                while (!skip)
                {
                    switch (state)
                    {
                    case ParserState.ExpectField:
                        if (curChar.IsEof || curChar.IsEol)
                        {
                            if (result.Count > 0)                                     // Special case - empty string not treated as single empty value
                            {
                                result.Add("");
                            }
                            return(result.ToArray());
                        }

                        if (curChar.Char == separator)
                        {
                            result.Add("");
                            state = ParserState.AfterField;
                            break;
                        }

                        skip = true;
                        if (curChar.IsWhitespace)
                        {
                            break;
                        }

                        curField = new StringBuilder();

                        if (curChar.IsDoubleQuota)
                        {
                            state = ParserState.QuotedField;
                            break;
                        }

                        state = ParserState.Field;
                        curField.Append(curChar.Char);
                        break;

                    case ParserState.Field:
                        Debug.Assert(curField != null, "curField != null");
                        if (curChar.IsEof || curChar.IsEol || curChar.Char == separator)
                        {
                            result.Add(curField.ToString().Trim());
                            state = ParserState.AfterField;
                            break;
                        }

                        skip = true;
                        curField.Append(curChar.Char);
                        break;

                    case ParserState.QuotedField:
                        Debug.Assert(curField != null, "curField != null");
                        if (curChar.IsEof)
                        {
                            throw new FormatException($"Unexpected EOF at line {lineNum} column {column}");
                        }

                        skip = true;
                        if (curChar.IsEol)
                        {
                            curField.Append("\r\n");
                            break;
                        }
                        if (curChar.IsDoubleQuota)
                        {
                            var peek = curChar.Peek();
                            if (peek.IsDoubleQuota)                                     // Escaped '"'
                            {
                                curField.Append('"');
                                curChar = curChar.Next();
                            }
                            else
                            {
                                result.Add(curField.ToString());
                                state = ParserState.AfterField;
                            }
                            break;
                        }
                        curField.Append(curChar.Char);
                        break;

                    case ParserState.AfterField:
                        if (curChar.IsEof || curChar.IsEol)
                        {
                            return(result.ToArray());
                        }
                        skip = true;
                        if (curChar.IsWhitespace)
                        {
                            continue;
                        }
                        if (curChar.Char == separator)
                        {
                            state = ParserState.ExpectField;
                            break;
                        }
                        throw new FormatException($"Unexpected char '{curChar.Char}' at line {lineNum} column {column}");

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }

                curChar = curChar.Next();
                column++;
                if (curChar.IsEol)
                {
                    lineNum++;
                    column = 1;
                }
            }
        }