Browse Source

* fcl-base/dbase: memo definitions clarified

git-svn-id: trunk@24159 -
reiniero 12 years ago
parent
commit
5c6b0d39e9

+ 4 - 5
packages/fcl-db/src/dbase/dbf_dbffile.pas

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

+ 9 - 9
packages/fcl-db/src/dbase/dbf_fields.pas

@@ -80,7 +80,7 @@ type
     // Native dbf field type
     // Native dbf field type
     property NativeFieldType: TDbfFieldType read FNativeFieldType write SetNativeFieldType;
     property NativeFieldType: TDbfFieldType read FNativeFieldType write SetNativeFieldType;
     property NullPosition: integer read FNullPosition write FNullPosition;
     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;
     property Size: Integer         read FSize      write SetSize;
     // Precision in dbase file (not VCL/LCL)
     // Precision in dbase file (not VCL/LCL)
     property Precision: Integer    read FPrecision write SetPrecision;
     property Precision: Integer    read FPrecision write SetPrecision;
@@ -118,7 +118,7 @@ uses
 
 
 const
 const
 (*
 (*
-The theory is:
+The theory for Delphi/FPC is:
     ftSmallint  16 bits = -32768 to 32767
     ftSmallint  16 bits = -32768 to 32767
                           123456 = 6 digit max theorically
                           123456 = 6 digit max theorically
                           DIGITS_SMALLINT = 6;
                           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
 So I oversize the field type in order to accept anything coming from the
 database.
 database.
     ftSmallint  16 bits = -32768 to 32767
     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
     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
     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_SMALLINT = 4;
   DIGITS_INTEGER = 9;
   DIGITS_INTEGER = 9;

+ 22 - 15
packages/fcl-db/src/dbase/dbf_memo.pas

@@ -101,16 +101,20 @@ uses
 //=== Memo and binary fields support
 //=== Memo and binary fields support
 //====================================================================
 //====================================================================
 type
 type
-
+  // DBase III+ dbt memo file
   PDbtHdr = ^rDbtHdr;
   PDbtHdr = ^rDbtHdr;
   rDbtHdr = record
   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
     DbfFile   : array [0..7] of Byte;   // 8..15
+    // DBase III only: version number $03
     bVer      : Byte;                   // 16
     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
     BlockLen  : Word;                   // 20..21
-    Dummy3    : array [22..511] of Byte;
+    Dummy3    : array [22..511] of Byte;// 22..511 First block; garbage contents
   end;
   end;
 
 
   PFptHdr = ^rFptHdr;
   PFptHdr = ^rFptHdr;
@@ -121,10 +125,12 @@ type
     Dummy3    : array [8..511] of Byte;
     Dummy3    : array [8..511] of Byte;
   end;
   end;
 
 
+  // Header of a memo data block:
   PBlockHdr = ^rBlockHdr;
   PBlockHdr = ^rBlockHdr;
   rBlockHdr = record
   rBlockHdr = record
-    MemoType  : Cardinal;
-    MemoSize  : Cardinal;
+    // DBase IV(+) identifier: $FF $FF $08 $00
+    MemoType  : Cardinal; // 0..4
+    MemoSize  : Cardinal; // 5..7
   end;
   end;
 
 
 
 
@@ -184,7 +190,8 @@ begin
     RecordSize := GetBlockLen;
     RecordSize := GetBlockLen;
     // checking for right blocksize not needed for foxpro?
     // checking for right blocksize not needed for foxpro?
     // mod 128 <> 0 <-> and 0x7F <> 0
     // 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
     begin
       SetBlockLen(512);
       SetBlockLen(512);
       RecordSize := 512;
       RecordSize := 512;
@@ -271,15 +278,15 @@ begin
     // dbase III memo
     // dbase III memo
     done := false;
     done := false;
     repeat
     repeat
-      // scan for EOF
+      // scan for EOF marker
       endMemo := MemScan(FBuffer, $1A, RecordSize);
       endMemo := MemScan(FBuffer, $1A, RecordSize);
       // EOF found?
       // EOF found?
       if endMemo <> nil then
       if endMemo <> nil then
       begin
       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
         begin
-          // yes, EOF found
           done := true;
           done := true;
           numBytes := endMemo - FBuffer;
           numBytes := endMemo - FBuffer;
         end else begin
         end else begin
@@ -344,7 +351,7 @@ begin
     begin
     begin
       bytesBefore := SizeOf(rBlockHdr);
       bytesBefore := SizeOf(rBlockHdr);
       bytesAfter := 0;
       bytesAfter := 0;
-    end else begin                      // dBase3 type
+    end else begin                      // dBase3 type, Clipper?
       bytesBefore := 0;
       bytesBefore := 0;
       bytesAfter := 2;
       bytesAfter := 2;
     end;
     end;
@@ -383,7 +390,7 @@ begin
     repeat
     repeat
       // read bytes, don't overwrite header
       // read bytes, don't overwrite header
       readBytes := Src.Read(FBuffer[bytesBefore], RecordSize{PDbtHdr(Header).BlockLen}-bytesBefore);
       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
       while (readBytes < RecordSize - bytesBefore) and (bytesAfter > 0) do
       begin
       begin
         FBuffer[readBytes] := #$1A;
         FBuffer[readBytes] := #$1A;
@@ -428,7 +435,7 @@ end;
 
 
 function  TDbaseMemoFile.GetMemoSize: Integer;
 function  TDbaseMemoFile.GetMemoSize: Integer;
 begin
 begin
-  // dBase4 memofiles contain small 'header'
+  // dBase4 memofiles contain a small 'header'
   if PInteger(@FBuffer[0])^ = Integer(SwapIntLE($0008FFFF)) then
   if PInteger(@FBuffer[0])^ = Integer(SwapIntLE($0008FFFF)) then
     Result := SwapIntLE(PBlockHdr(FBuffer)^.MemoSize)-8
     Result := SwapIntLE(PBlockHdr(FBuffer)^.MemoSize)-8
   else
   else

+ 1 - 1
packages/fcl-db/src/dbase/dbf_struct.inc

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