private object[] ReadRowFromBufferMemo(ReadOnlySpan <byte> rowBuf, int index, Stream memofs, short memoBlocksize) { var rowData = new object[dbfHeader.Fields.Count]; INullFieldHandler nullFieldHandler = null; if (nullField != null) { rowData[nullField.Index] = nullFieldDataHandler(index, rowBuf.Slice(nullField.Displacement, nullField.Length), nullField, null); nullFieldHandler = (INullFieldHandler)nullFieldHandlerFactory(index, rowBuf.Slice(nullField.Displacement, nullField.Length), nullField, null); } Span <byte> intBuf = stackalloc byte[4]; for (var i = 0; i < rowData.Length; i++) { var field = dbfHeader.Fields[i]; if (field == nullField) { continue; } var hasHandler = DbfTypeMap.TryGetValue(field.Type, out var handler); if (!hasHandler) { continue; } var hasNullFlag = false; if (nullFieldHandler != null && field.CanBeNull) { hasNullFlag = nullFieldHandler.IsNull(field.NullFieldIndex); } if (field.Type == 'M') { if (hasNullFlag) { continue; } var offset = (int)handler(index, rowBuf.Slice(field.Displacement, field.Length), field, TextEncoding); if (offset == 0) { rowData[i] = ""; continue; } var targetPos = 4 + offset * memoBlocksize; var memoPos = memofs.Position; if (memoPos < targetPos) { memofs.Seek(targetPos - memoPos, SeekOrigin.Current); } else { memofs.Position = targetPos; } var len = memofs.ReadIntBE(intBuf); if ((field.Flags & DbfFieldFlags.Binary) != 0) { var memoBuf = new byte[len]; memofs.Read(memoBuf, 0, len); rowData[i] = memoBuf; } else { var memoBuf = bufferPool.Rent(len); memofs.Read(memoBuf, 0, len); try { rowData[i] = TextEncoding.GetString(memoBuf, 0, len); } finally { bufferPool.Return(memoBuf); } } } else if (field.Type == 'V' || field.Type == 'Q') { if (hasNullFlag) { rowData[i] = null; } else if (nullFieldHandler.IsNull(field.VarLengthSizeIndex)) { var valueLength = rowBuf[field.Displacement + field.Length - 1]; rowData[i] = handler(index, rowBuf.Slice(field.Displacement, valueLength), field, TextEncoding); } else { rowData[i] = handler(index, rowBuf.Slice(field.Displacement, field.Length), field, TextEncoding); } } else { if (hasNullFlag) { continue; } rowData[i] = handler(index, rowBuf.Slice(field.Displacement, field.Length), field, TextEncoding); } } return(rowData); }
private object[] ReadRowFromBuffer(ReadOnlySpan <byte> rowBuf, int index) { var rowData = new object[dbfHeader.Fields.Count]; INullFieldHandler nullFieldHandler = null; if (nullField != null) { rowData[nullField.Index] = nullFieldDataHandler(index, rowBuf.Slice(nullField.Displacement, nullField.Length), nullField, null); nullFieldHandler = (INullFieldHandler)nullFieldHandlerFactory(index, rowBuf.Slice(nullField.Displacement, nullField.Length), nullField, null); } for (var i = 0; i < rowData.Length; i++) { var field = dbfHeader.Fields[i]; if (field == nullField) { continue; } var hasHandler = DbfTypeMap.TryGetValue(field.Type, out var handler); if (!hasHandler) { continue; } var hasNullFlag = false; if (nullFieldHandler != null && field.CanBeNull) { hasNullFlag = nullFieldHandler.IsNull(field.NullFieldIndex); } if (field.Type == 'M' || field.Type == 'W' || field.Type == 'G') { if (hasNullFlag) { continue; } var memoPointer = handler(index, rowBuf.Slice(field.Displacement, field.Length), field, TextEncoding); rowData[i] = $"MEMO@{memoPointer}"; } else if (field.Type == 'V' || field.Type == 'Q') { if (hasNullFlag) { rowData[i] = null; } else if (nullFieldHandler.IsNull(field.VarLengthSizeIndex)) { var valueLength = rowBuf[field.Displacement + field.Length - 1]; rowData[i] = handler(index, rowBuf.Slice(field.Displacement, valueLength), field, TextEncoding); } else { rowData[i] = handler(index, rowBuf.Slice(field.Displacement, field.Length), field, TextEncoding); } } else { if (hasNullFlag) { continue; } rowData[i] = handler(index, rowBuf.Slice(field.Displacement, field.Length), field, TextEncoding); } } return(rowData); }