dbf_idxcur.pas 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. unit dbf_idxcur;
  2. interface
  3. {$I dbf_common.inc}
  4. uses
  5. SysUtils,
  6. Classes,
  7. dbf_cursor,
  8. dbf_idxfile,
  9. dbf_prsdef,
  10. dbf_common;
  11. type
  12. //====================================================================
  13. //=== Index support
  14. //====================================================================
  15. TIndexCursor = class(TVirtualCursor)
  16. private
  17. FIndexFile: TIndexFile;
  18. protected
  19. function GetPhysicalRecNo: Integer; override;
  20. function GetSequentialRecNo: Integer; override;
  21. function GetSequentialRecordCount: Integer; override;
  22. procedure SetPhysicalRecNo(RecNo: Integer); override;
  23. procedure SetSequentialRecNo(RecNo: Integer); override;
  24. public
  25. constructor Create(DbfIndexFile: TIndexFile);
  26. destructor Destroy; override;
  27. function Next: Boolean; override;
  28. function Prev: Boolean; override;
  29. procedure First; override;
  30. procedure Last; override;
  31. procedure Insert(RecNo: Integer; Buffer: PChar);
  32. procedure Update(RecNo: Integer; PrevBuffer, NewBuffer: PChar);
  33. {$ifdef SUPPORT_VARIANTS}
  34. procedure VariantToBuffer(Key: Variant; ABuffer: PChar);
  35. {$endif}
  36. function CheckUserKey(Key: PChar; StringBuf: PChar): PChar;
  37. property IndexFile: TIndexFile read FIndexFile;
  38. end;
  39. //====================================================================
  40. // TIndexCursor = class;
  41. //====================================================================
  42. PIndexPosInfo = ^TIndexPage;
  43. //====================================================================
  44. implementation
  45. //==========================================================
  46. //============ TIndexCursor
  47. //==========================================================
  48. constructor TIndexCursor.Create(DbfIndexFile: TIndexFile);
  49. begin
  50. inherited Create(DbfIndexFile);
  51. FIndexFile := DbfIndexFile;
  52. end;
  53. destructor TIndexCursor.Destroy; {override;}
  54. begin
  55. inherited Destroy;
  56. end;
  57. procedure TIndexCursor.Insert(RecNo: Integer; Buffer: PChar);
  58. begin
  59. TIndexFile(PagedFile).Insert(RecNo,Buffer);
  60. // TODO SET RecNo and Key
  61. end;
  62. procedure TIndexCursor.Update(RecNo: Integer; PrevBuffer, NewBuffer: PChar);
  63. begin
  64. TIndexFile(PagedFile).Update(RecNo, PrevBuffer, NewBuffer);
  65. end;
  66. procedure TIndexCursor.First;
  67. begin
  68. TIndexFile(PagedFile).First;
  69. end;
  70. procedure TIndexCursor.Last;
  71. begin
  72. TIndexFile(PagedFile).Last;
  73. end;
  74. function TIndexCursor.Prev: Boolean;
  75. begin
  76. Result := TIndexFile(PagedFile).Prev;
  77. end;
  78. function TIndexCursor.Next: Boolean;
  79. begin
  80. Result := TIndexFile(PagedFile).Next;
  81. end;
  82. function TIndexCursor.GetPhysicalRecNo: Integer;
  83. begin
  84. Result := TIndexFile(PagedFile).PhysicalRecNo;
  85. end;
  86. procedure TIndexCursor.SetPhysicalRecNo(RecNo: Integer);
  87. begin
  88. TIndexFile(PagedFile).PhysicalRecNo := RecNo;
  89. end;
  90. function TIndexCursor.GetSequentialRecordCount: Integer;
  91. begin
  92. Result := TIndexFile(PagedFile).SequentialRecordCount;
  93. end;
  94. function TIndexCursor.GetSequentialRecNo: Integer;
  95. begin
  96. Result := TIndexFile(PagedFile).SequentialRecNo;
  97. end;
  98. procedure TIndexCursor.SetSequentialRecNo(RecNo: Integer);
  99. begin
  100. TIndexFile(PagedFile).SequentialRecNo := RecNo;
  101. end;
  102. {$ifdef SUPPORT_VARIANTS}
  103. procedure TIndexCursor.VariantToBuffer(Key: Variant; ABuffer: PChar);
  104. // assumes ABuffer is large enough ie. at least max key size
  105. var
  106. currLen: Integer;
  107. begin
  108. if (TIndexFile(PagedFile).KeyType='N') then
  109. begin
  110. PDouble(ABuffer)^ := Key;
  111. if (TIndexFile(PagedFile).IndexVersion <> xBaseIII) then
  112. begin
  113. // make copy of userbcd to buffer
  114. Move(TIndexFile(PagedFile).PrepareKey(ABuffer, etFloat)[0], ABuffer[0], 11);
  115. end
  116. end else begin
  117. StrPLCopy(ABuffer, Key, TIndexFile(PagedFile).KeyLen);
  118. // we have null-terminated string, pad with spaces if string too short
  119. currLen := StrLen(ABuffer);
  120. FillChar(ABuffer[currLen], TIndexFile(PagedFile).KeyLen-currLen, ' ');
  121. end;
  122. end;
  123. {$endif}
  124. function TIndexCursor.CheckUserKey(Key: PChar; StringBuf: PChar): PChar;
  125. var
  126. keyLen, userLen: Integer;
  127. begin
  128. // default is to use key
  129. Result := Key;
  130. // if key is double, then no check
  131. if (TIndexFile(PagedFile).KeyType = 'N') then
  132. begin
  133. // nothing needs to be done
  134. end else begin
  135. // check if string long enough then no copying needed
  136. userLen := StrLen(Key);
  137. keyLen := TIndexFile(PagedFile).KeyLen;
  138. if userLen < keyLen then
  139. begin
  140. // copy string
  141. Move(Key^, StringBuf[0], userLen);
  142. // add spaces to searchstring
  143. FillChar(StringBuf[userLen], keyLen - userLen, ' ');
  144. // set buffer to temporary buffer
  145. Result := StringBuf;
  146. end;
  147. end;
  148. end;
  149. end.