* fcl-base/dbase: memo definitions clarified

git-svn-id: trunk@24159 -
This commit is contained in:
reiniero 2013-04-05 13:21:54 +00:00
parent 17f65340c4
commit 5c6b0d39e9
4 changed files with 36 additions and 30 deletions

View File

@ -352,7 +352,7 @@ var
// http://msdn.microsoft.com/en-US/library/st4a0s68%28v=vs.80%29.aspx
case version of
$30, $31, $32: FDbfVersion:=xVisualFoxPro;
$F5: FDbfVersion:=xFoxPro;
$F5, $FB: FDbfVersion:=xFoxPro;
end;
if FDbfVersion = xUnknown then
case (version and $07) of
@ -366,11 +366,7 @@ var
$02, $05:
FDbfVersion := xFoxPro;
else
// todo: check visual foxpro, modify
if ((version and $FE) = $30) or (version = $F5) or (version = $FB) then
begin
FDbfVersion := xFoxPro;
end else begin
// not a valid DBF file
raise EDbfError.Create(STRING_INVALID_DBF_FILE);
end;
@ -677,6 +673,8 @@ begin
{$endif}
then
begin
// Up to 32kb strings
// Stores high byte of size in precision, low in size
lPrec := lSize shr 8;
lSize := lSize and $FF;
end;
@ -699,6 +697,7 @@ begin
lFieldDescIII.FieldPrecision := lPrec;
if (FDbfVersion in [xFoxPro,xVisualFoxPro]) then
lFieldDescIII.FieldOffset := SwapIntLE(lFieldOffset);
// Adjust the version info if needed for supporting field types used:
if (PDbfHdr(Header)^.VerDBF = $02) and (lFieldDef.NativeFieldType in ['0', 'Y', 'T', 'O', '+']) then
PDbfHdr(Header)^.VerDBF := $30; {Visual FoxPro}
if (PDbfHdr(Header)^.VerDBF = $30) and (lFieldDef.NativeFieldType = '+') then

View File

@ -80,7 +80,7 @@ type
// Native dbf field type
property NativeFieldType: TDbfFieldType read FNativeFieldType write SetNativeFieldType;
property NullPosition: integer read FNullPosition write FNullPosition;
// Size in dbase file (not VCL/LCL)
// Size in memory (not VCL/LCL)
property Size: Integer read FSize write SetSize;
// Precision in dbase file (not VCL/LCL)
property Precision: Integer read FPrecision write SetPrecision;
@ -118,7 +118,7 @@ uses
const
(*
The theory is:
The theory for Delphi/FPC is:
ftSmallint 16 bits = -32768 to 32767
123456 = 6 digit max theorically
DIGITS_SMALLINT = 6;
@ -135,15 +135,15 @@ be able to handles fields with 999999 (6 digits).
So I oversize the field type in order to accept anything coming from the
database.
ftSmallint 16 bits = -32768 to 32767
-999 to 9999
4 digits max theorically
DIGITS_SMALLINT = 4;
... dbf supports: -999 to 9999
4 digits max in practice
therefore DIGITS_SMALLINT = 4;
ftInteger 32 bits = -2147483648 to 2147483647
-99999999 to 999999999 12345678901 = 11 digits max
DIGITS_INTEGER = 9;
... dbf supports: -99999999 to 999999999 12345678901 = 11 digits max
therefore DIGITS_INTEGER = 9;
ftLargeInt 64 bits = -9223372036854775808 to 9223372036854775807
-99999999999999999 to 999999999999999999
DIGITS_LARGEINT = 18;
... dbf supports: -99999999999999999 to 999999999999999999
therefore DIGITS_LARGEINT = 18;
*)
DIGITS_SMALLINT = 4;
DIGITS_INTEGER = 9;

View File

@ -101,16 +101,20 @@ uses
//=== Memo and binary fields support
//====================================================================
type
// DBase III+ dbt memo file
PDbtHdr = ^rDbtHdr;
rDbtHdr = record
NextBlock : dword;
Dummy : array [4..7] of Byte;
NextBlock : dword; // 0..3
// Dummy in DBaseIII; size of blocks in memo file; default 512 bytes
BlockSize : dword; // 4..7
// DBF file name without extension
DbfFile : array [0..7] of Byte; // 8..15
// DBase III only: version number $03
bVer : Byte; // 16
Dummy2 : array [17..19] of Byte;
Dummy2 : array [17..19] of Byte; // 17..19
// Block length in bytes; DBaseIII: always $01
BlockLen : Word; // 20..21
Dummy3 : array [22..511] of Byte;
Dummy3 : array [22..511] of Byte;// 22..511 First block; garbage contents
end;
PFptHdr = ^rFptHdr;
@ -121,10 +125,12 @@ type
Dummy3 : array [8..511] of Byte;
end;
// Header of a memo data block:
PBlockHdr = ^rBlockHdr;
rBlockHdr = record
MemoType : Cardinal;
MemoSize : Cardinal;
// DBase IV(+) identifier: $FF $FF $08 $00
MemoType : Cardinal; // 0..4
MemoSize : Cardinal; // 5..7
end;
@ -184,7 +190,8 @@ begin
RecordSize := GetBlockLen;
// checking for right blocksize not needed for foxpro?
// mod 128 <> 0 <-> and 0x7F <> 0
if (RecordSize = 0) and ((FDbfVersion in [xFoxPro,xVisualFoxPro]) or ((RecordSize and $7F) <> 0)) then
if (RecordSize = 0) and
((FDbfVersion in [xFoxPro,xVisualFoxPro]) or ((RecordSize and $7F) <> 0)) then
begin
SetBlockLen(512);
RecordSize := 512;
@ -271,15 +278,15 @@ begin
// dbase III memo
done := false;
repeat
// scan for EOF
// scan for EOF marker
endMemo := MemScan(FBuffer, $1A, RecordSize);
// EOF found?
if endMemo <> nil then
begin
// really EOF?
if (endMemo-FBuffer < RecordSize - 1) and ((endMemo[1] = #$1A) or (endMemo[1] = #0)) then
// really EOF? expect another 1A or null character
if (endMemo-FBuffer < RecordSize - 1) and
((endMemo[1] = #$1A) or (endMemo[1] = #0)) then
begin
// yes, EOF found
done := true;
numBytes := endMemo - FBuffer;
end else begin
@ -344,7 +351,7 @@ begin
begin
bytesBefore := SizeOf(rBlockHdr);
bytesAfter := 0;
end else begin // dBase3 type
end else begin // dBase3 type, Clipper?
bytesBefore := 0;
bytesAfter := 2;
end;
@ -383,7 +390,7 @@ begin
repeat
// read bytes, don't overwrite header
readBytes := Src.Read(FBuffer[bytesBefore], RecordSize{PDbtHdr(Header).BlockLen}-bytesBefore);
// end of input data reached ? check if need to write block terminators
// end of input data reached? check if we need to write block terminators
while (readBytes < RecordSize - bytesBefore) and (bytesAfter > 0) do
begin
FBuffer[readBytes] := #$1A;
@ -428,7 +435,7 @@ end;
function TDbaseMemoFile.GetMemoSize: Integer;
begin
// dBase4 memofiles contain small 'header'
// dBase4 memofiles contain a small 'header'
if PInteger(@FBuffer[0])^ = Integer(SwapIntLE($0008FFFF)) then
Result := SwapIntLE(PBlockHdr(FBuffer)^.MemoSize)-8
else

View File

@ -51,9 +51,9 @@ type
rFieldDescIII = packed record
FieldName : array[0..10] of Char;
FieldType : Char; // 11
FieldOffset : Integer; // 12..15
// FieldOffset only applicable to (visual) foxpro databases
// DBase III uses it for address in memory
FieldOffset : Integer; // 12..15
FieldSize : Byte; // 16
FieldPrecision : Byte; // 17, also known as decimal count
FoxProFlags : Byte; // 18