예제 #1
0
        /// <summary>Parses a single row of data from the specified string.</summary>
        /// <param name="properties">The csv properties.</param>
        /// <param name="layout">The row layout.</param>
        /// <param name="data">The buffer to parse.</param>
        /// <returns>Returns a new <see cref="Row" /> instance.</returns>
        public static Row ParseRow(CsvProperties properties, RowLayout layout, string data)
        {
            try
            {
                var fieldCount       = layout.FieldCount;
                var fieldNumber      = 0;
                var ident            = new Queue <char>();
                var identInARowCount = 0;
                var currentValue     = new List <char>();
                var i      = -1;
                var values = new object[fieldCount];
                while (fieldNumber < fieldCount)
                {
                    ++i;
                    if ((i == data.Length) && (fieldNumber == (fieldCount - 1)))
                    {
                        break;
                    }

                    if (i >= data.Length)
                    {
                        throw new InvalidDataException("Unexpected end of input!");
                    }

                    if (properties.Separator == data[i])
                    {
                        if (ident.Count == 0)
                        {
                            identInARowCount = 0;
                            if (properties.StringMarker.HasValue)
                            {
                                values[fieldNumber] = layout.ParseValue(fieldNumber, new string(currentValue.ToArray()).Unescape(),
                                                                        properties.StringMarker.Value.ToString(), properties.Format);
                            }
                            else
                            {
                                values[fieldNumber] = layout.ParseValue(fieldNumber, new string(currentValue.ToArray()).Unescape(), string.Empty,
                                                                        properties.Format);
                            }

                            fieldNumber++;
                            currentValue.Clear();
                            continue;
                        }
                    }

                    if (properties.StringMarker == data[i])
                    {
                        identInARowCount++;
                        if ((ident.Count > 0) && (ident.Peek() == data[i]))
                        {
                            ident.Dequeue();
                            if (identInARowCount > 1)
                            {
                                // escaped char
                                currentValue.Add(data[i]);
                            }
                        }
                        else
                        {
                            ident.Enqueue(data[i]);
                        }
                    }
                    else
                    {
                        identInARowCount = 0;
                        currentValue.Add(data[i]);
                    }
                }

                if (ident.Count > 0)
                {
                    throw new InvalidDataException("Invalid ident/escaping!");
                }

                if (properties.StringMarker.HasValue)
                {
                    values[fieldNumber] = layout.ParseValue(fieldNumber, new string(currentValue.ToArray()).Unescape(),
                                                            properties.StringMarker.Value.ToString(), properties.Format);
                }
                else
                {
                    values[fieldNumber] = layout.ParseValue(fieldNumber, new string(currentValue.ToArray()).Unescape(), string.Empty, properties.Format);
                }

                fieldNumber++;
                if (i < data.Length)
                {
                    if (properties.Separator == data[i])
                    {
                        i++;
                    }

                    if (i < data.Length)
                    {
                        throw new InvalidDataException("Additional data at end of line!");
                    }
                }

                return(new Row(layout, values, false));
            }
            catch (EndOfStreamException)
            {
                if (data.Length > 0)
                {
                    throw;
                }

                return(null);
            }
            catch (Exception ex)
            {
                throw new InvalidDataException("Error while reading row data!", ex);
            }
        }
예제 #2
0
        internal static Row ReadCurrentRow(DataReader reader, int version, RowLayout layout)
        {
            if (version < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(version));
            }

            if (version > 4)
            {
                throw new NotSupportedException("Version not supported!");
            }

            var dataStart = reader.BaseStream.Position;
            var dataSize  = reader.Read7BitEncodedInt32();

            if (dataSize == 0)
            {
                return(null);
            }

            var values = new object[layout.FieldCount];

            for (var i = 0; i < layout.FieldCount; i++)
            {
                var field    = layout[i];
                var dataType = field.DataType;
                switch (dataType)
                {
                case DataType.Binary:
                    if (version >= 3)
                    {
                        values[i] = reader.ReadBytes();
                    }
                    else
                    {
                        var size = reader.ReadInt32();
                        values[i] = reader.ReadBytes(size);
                    }

                    break;

                case DataType.Bool:
                    values[i] = reader.ReadBool();
                    break;

                case DataType.DateTime:
                    values[i] = new DateTime(reader.ReadInt64(), field.DateTimeKind);
                    break;

                case DataType.TimeSpan:
                    values[i] = new TimeSpan(reader.ReadInt64());
                    break;

                case DataType.Int8:
                    values[i] = reader.ReadInt8();
                    break;

                case DataType.Int16:
                    values[i] = reader.ReadInt16();
                    break;

                case DataType.Int32:
                    if (version == 1)
                    {
                        values[i] = reader.ReadInt32();
                        break;
                    }

                    values[i] = reader.Read7BitEncodedInt32();
                    break;

                case DataType.Int64:
                    if (version == 1)
                    {
                        values[i] = reader.ReadInt64();
                        break;
                    }

                    values[i] = reader.Read7BitEncodedInt64();
                    break;

                case DataType.UInt32:
                    if (version == 1)
                    {
                        values[i] = reader.ReadUInt32();
                        break;
                    }

                    values[i] = reader.Read7BitEncodedUInt32();
                    break;

                case DataType.UInt64:
                    if (version == 1)
                    {
                        values[i] = reader.ReadUInt64();
                        break;
                    }

                    values[i] = reader.Read7BitEncodedUInt64();
                    break;

                case DataType.UInt8:
                    values[i] = reader.ReadUInt8();
                    break;

                case DataType.UInt16:
                    values[i] = reader.ReadUInt16();
                    break;

                case DataType.Char:
                    values[i] = reader.ReadChar();
                    break;

                case DataType.Single:
                    values[i] = reader.ReadSingle();
                    break;

                case DataType.Double:
                    values[i] = reader.ReadDouble();
                    break;

                case DataType.Decimal:
                    values[i] = reader.ReadDecimal();
                    break;

                case DataType.String:
                    values[i] = reader.ReadString();
                    break;

                case DataType.Enum:
                    values[i] = layout.EnumValue(i, reader.Read7BitEncodedInt64());
                    break;

                case DataType.User:
                    values[i] = layout.ParseValue(i, reader.ReadString(), null);
                    break;

                default: throw new NotImplementedException($"Datatype {dataType} not implemented!");
                }
            }

            var skip = (dataStart + dataSize) - reader.BaseStream.Position;

            if (skip < 0)
            {
                throw new FormatException();
            }

            if (skip > 0)
            {
                reader.BaseStream.Seek(skip, SeekOrigin.Current);
            }

            return(new Row(layout, values, false));
        }