dbf_common.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. unit dbf_common;
  2. interface
  3. {$I dbf_common.inc}
  4. uses
  5. SysUtils, Classes, DB
  6. {$ifndef WIN32}
  7. , Types, dbf_wtil
  8. {$ifdef KYLIX}
  9. , Libc
  10. {$endif}
  11. {$endif}
  12. ;
  13. const
  14. TDBF_MAJOR_VERSION = 6;
  15. TDBF_MINOR_VERSION = 48;
  16. TDBF_SUB_MINOR_VERSION = 0;
  17. TDBF_TABLELEVEL_FOXPRO = 25;
  18. type
  19. EDbfError = class (EDatabaseError);
  20. EDbfWriteError = class (EDbfError);
  21. TDbfFieldType = char;
  22. TXBaseVersion = (xUnknown, xClipper, xBaseIII, xBaseIV, xBaseV, xFoxPro, xBaseVII);
  23. TSearchKeyType = (stEqual, stGreaterEqual, stGreater);
  24. TDateTimeHandling = (dtDateTime, dtBDETimeStamp);
  25. //-------------------------------------
  26. PDateTime = ^TDateTime;
  27. {$ifdef FPC_VERSION}
  28. TDateTimeAlias = type TDateTime;
  29. TDateTimeRec = record
  30. case TFieldType of
  31. ftDate: (Date: Longint);
  32. ftTime: (Time: Longint);
  33. ftDateTime: (DateTime: TDateTimeAlias);
  34. end;
  35. {$else}
  36. PtrInt = Longint;
  37. {$endif}
  38. PSmallInt = ^SmallInt;
  39. PCardinal = ^Cardinal;
  40. PDouble = ^Double;
  41. PString = ^String;
  42. PDateTimeRec = ^TDateTimeRec;
  43. {$ifdef SUPPORT_INT64}
  44. PLargeInt = ^Int64;
  45. {$endif}
  46. {$ifdef DELPHI_3}
  47. dword = cardinal;
  48. {$endif}
  49. //-------------------------------------
  50. {$ifndef SUPPORT_FREEANDNIL}
  51. // some procedures for the less lucky who don't have newer versions yet :-)
  52. procedure FreeAndNil(var v);
  53. {$endif}
  54. procedure FreeMemAndNil(var P: Pointer);
  55. //-------------------------------------
  56. {$ifndef SUPPORT_PATHDELIM}
  57. const
  58. {$ifdef WIN32}
  59. PathDelim = '\';
  60. {$else}
  61. PathDelim = '/';
  62. {$endif}
  63. {$endif}
  64. {$ifndef SUPPORT_INCLTRAILPATHDELIM}
  65. function IncludeTrailingPathDelimiter(const Path: string): string;
  66. {$endif}
  67. //-------------------------------------
  68. function GetCompletePath(const Base, Path: string): string;
  69. function GetCompleteFileName(const Base, FileName: string): string;
  70. function IsFullFilePath(const Path: string): Boolean; // full means not relative
  71. function DateTimeToBDETimeStamp(aDT: TDateTime): double;
  72. function BDETimeStampToDateTime(aBT: double): TDateTime;
  73. function GetStrFromInt(Val: Integer; const Dst: PChar): Integer;
  74. procedure GetStrFromInt_Width(Val: Integer; const Width: Integer; const Dst: PChar; const PadChar: Char);
  75. {$ifdef SUPPORT_INT64}
  76. function GetStrFromInt64(Val: Int64; const Dst: PChar): Integer;
  77. procedure GetStrFromInt64_Width(Val: Int64; const Width: Integer; const Dst: PChar; const PadChar: Char);
  78. {$endif}
  79. procedure FindNextName(BaseName: string; var OutName: string; var Modifier: Integer);
  80. {$ifdef USE_CACHE}
  81. function GetFreeMemory: Integer;
  82. {$endif}
  83. // OH 2000-11-15 dBase7 support. Swap Byte order for 4 and 8 Byte Integer
  84. function SwapWord(const Value: word): word;
  85. function SwapInt(const Value: dword): dword;
  86. { SwapInt64 NOTE: do not call with same value for Value and Result ! }
  87. procedure SwapInt64(Value, Result: Pointer); register;
  88. function TranslateString(FromCP, ToCP: Cardinal; Src, Dest: PChar; Length: Integer): Integer;
  89. // Returns a pointer to the first occurence of Chr in Str within the first Length characters
  90. // Does not stop at null (#0) terminator!
  91. function MemScan(const Buffer: Pointer; Chr: Byte; Length: Integer): Pointer;
  92. // Delphi 3 does not have a Min function
  93. {$ifdef DELPHI_3}
  94. {$ifndef DELPHI_4}
  95. function Min(x, y: integer): integer;
  96. function Max(x, y: integer): integer;
  97. {$endif}
  98. {$endif}
  99. implementation
  100. {$ifdef WIN32}
  101. uses
  102. Windows;
  103. {$endif}
  104. //====================================================================
  105. function GetCompletePath(const Base, Path: string): string;
  106. begin
  107. if IsFullFilePath(Path)
  108. then begin
  109. Result := Path;
  110. end else begin
  111. if Length(Base) > 0 then
  112. Result := ExpandFileName(IncludeTrailingPathDelimiter(Base) + Path)
  113. else
  114. Result := ExpandFileName(Path);
  115. end;
  116. // add last backslash if not present
  117. if Length(Result) > 0 then
  118. Result := IncludeTrailingPathDelimiter(Result);
  119. end;
  120. function IsFullFilePath(const Path: string): Boolean; // full means not relative
  121. begin
  122. {$ifdef WIN32}
  123. Result := Length(Path) > 1;
  124. if Result then
  125. // check for 'x:' or '\\' at start of path
  126. Result := ((Path[2]=':') and (upcase(Path[1]) in ['A'..'Z']))
  127. or ((Path[1]='\') and (Path[2]='\'));
  128. {$else} // Linux
  129. Result := Length(Path) > 0;
  130. if Result then
  131. Result := Path[1]='/';
  132. {$endif}
  133. end;
  134. //====================================================================
  135. function GetCompleteFileName(const Base, FileName: string): string;
  136. var
  137. lpath: string;
  138. lfile: string;
  139. begin
  140. lpath := GetCompletePath(Base, ExtractFilePath(FileName));
  141. lfile := ExtractFileName(FileName);
  142. lpath := lpath + lfile;
  143. result := lpath;
  144. end;
  145. // it seems there is no pascal function to convert an integer into a PChar???
  146. procedure GetStrFromInt_Width(Val: Integer; const Width: Integer; const Dst: PChar; const PadChar: Char);
  147. var
  148. Temp: array[0..10] of Char;
  149. I, J: Integer;
  150. NegSign: boolean;
  151. begin
  152. {$I getstrfromint.inc}
  153. end;
  154. {$ifdef SUPPORT_INT64}
  155. procedure GetStrFromInt64_Width(Val: Int64; const Width: Integer; const Dst: PChar; const PadChar: Char);
  156. var
  157. Temp: array[0..19] of Char;
  158. I, J: Integer;
  159. NegSign: boolean;
  160. begin
  161. {$I getstrfromint.inc}
  162. end;
  163. {$endif}
  164. // it seems there is no pascal function to convert an integer into a PChar???
  165. // NOTE: in dbf_dbffile.pas there is also a convert routine, but is slightly different
  166. function GetStrFromInt(Val: Integer; const Dst: PChar): Integer;
  167. var
  168. Temp: array[0..10] of Char;
  169. I, J: Integer;
  170. begin
  171. Val := Abs(Val);
  172. // we'll have to store characters backwards first
  173. I := 0;
  174. J := 0;
  175. repeat
  176. Temp[I] := Chr((Val mod 10) + Ord('0'));
  177. Val := Val div 10;
  178. Inc(I);
  179. until Val = 0;
  180. // remember number of digits
  181. Result := I;
  182. // copy value, remember: stored backwards
  183. repeat
  184. Dst[J] := Temp[I-1];
  185. Inc(J);
  186. Dec(I);
  187. until I = 0;
  188. // done!
  189. end;
  190. {$ifdef SUPPORT_INT64}
  191. function GetStrFromInt64(Val: Int64; const Dst: PChar): Integer;
  192. var
  193. Temp: array[0..19] of Char;
  194. I, J: Integer;
  195. begin
  196. Val := Abs(Val);
  197. // we'll have to store characters backwards first
  198. I := 0;
  199. J := 0;
  200. repeat
  201. Temp[I] := Chr((Val mod 10) + Ord('0'));
  202. Val := Val div 10;
  203. Inc(I);
  204. until Val = 0;
  205. // remember number of digits
  206. Result := I;
  207. // copy value, remember: stored backwards
  208. repeat
  209. Dst[J] := Temp[I-1];
  210. inc(J);
  211. dec(I);
  212. until I = 0;
  213. // done!
  214. end;
  215. {$endif}
  216. function DateTimeToBDETimeStamp(aDT: TDateTime): double;
  217. var
  218. aTS: TTimeStamp;
  219. begin
  220. aTS := DateTimeToTimeStamp(aDT);
  221. Result := TimeStampToMSecs(aTS);
  222. end;
  223. function BDETimeStampToDateTime(aBT: double): TDateTime;
  224. var
  225. aTS: TTimeStamp;
  226. begin
  227. aTS := MSecsToTimeStamp(aBT);
  228. Result := TimeStampToDateTime(aTS);
  229. end;
  230. //====================================================================
  231. {$ifndef SUPPORT_FREEANDNIL}
  232. procedure FreeAndNil(var v);
  233. var
  234. Temp: TObject;
  235. begin
  236. Temp := TObject(v);
  237. TObject(v) := nil;
  238. Temp.Free;
  239. end;
  240. {$endif}
  241. procedure FreeMemAndNil(var P: Pointer);
  242. var
  243. Temp: Pointer;
  244. begin
  245. Temp := P;
  246. P := nil;
  247. FreeMem(Temp);
  248. end;
  249. //====================================================================
  250. {$ifndef SUPPORT_INCLTRAILPATHDELIM}
  251. {$ifndef SUPPORT_INCLTRAILBACKSLASH}
  252. function IncludeTrailingPathDelimiter(const Path: string): string;
  253. var
  254. len: Integer;
  255. begin
  256. Result := Path;
  257. len := Length(Result);
  258. if len = 0 then
  259. Result := PathDelim
  260. else
  261. if Result[len] <> PathDelim then
  262. Result := Result + PathDelim;
  263. end;
  264. {$else}
  265. function IncludeTrailingPathDelimiter(const Path: string): string;
  266. begin
  267. {$ifdef WIN32}
  268. Result := IncludeTrailingBackslash(Path);
  269. {$else}
  270. Result := IncludeTrailingSlash(Path);
  271. {$endif}
  272. end;
  273. {$endif}
  274. {$endif}
  275. {$ifdef USE_CACHE}
  276. function GetFreeMemory: Integer;
  277. var
  278. MemStatus: TMemoryStatus;
  279. begin
  280. GlobalMemoryStatus(MemStatus);
  281. Result := MemStatus.dwAvailPhys;
  282. end;
  283. {$endif}
  284. //====================================================================
  285. // Utility routines
  286. //====================================================================
  287. function SwapWord(const Value: word): word;
  288. begin
  289. Result := ((Value and $FF) shl 8) or ((Value shr 8) and $FF);
  290. end;
  291. {$ifdef USE_ASSEMBLER_486_UP}
  292. function SwapInt(const Value: dword): dword; register; assembler;
  293. asm
  294. BSWAP EAX;
  295. end;
  296. procedure SwapInt64(Value {EAX}, Result {EDX}: Pointer); register; assembler;
  297. asm
  298. MOV ECX, dword ptr [EAX]
  299. MOV EAX, dword ptr [EAX + 4]
  300. BSWAP ECX
  301. BSWAP EAX
  302. MOV dword ptr [EDX+4], ECX
  303. MOV dword ptr [EDX], EAX
  304. end;
  305. {$else}
  306. function SwapInt(const Value: Cardinal): Cardinal;
  307. begin
  308. PByteArray(@Result)[0] := PByteArray(@Value)[3];
  309. PByteArray(@Result)[1] := PByteArray(@Value)[2];
  310. PByteArray(@Result)[2] := PByteArray(@Value)[1];
  311. PByteArray(@Result)[3] := PByteArray(@Value)[0];
  312. end;
  313. procedure SwapInt64(Value, Result: Pointer); register;
  314. var
  315. PtrResult: PByteArray;
  316. PtrSource: PByteArray;
  317. begin
  318. // temporary storage is actually not needed, but otherwise compiler crashes (?)
  319. PtrResult := PByteArray(Result);
  320. PtrSource := PByteArray(Value);
  321. PtrResult[0] := PtrSource[7];
  322. PtrResult[1] := PtrSource[6];
  323. PtrResult[2] := PtrSource[5];
  324. PtrResult[3] := PtrSource[4];
  325. PtrResult[4] := PtrSource[3];
  326. PtrResult[5] := PtrSource[2];
  327. PtrResult[6] := PtrSource[1];
  328. PtrResult[7] := PtrSource[0];
  329. end;
  330. {$endif}
  331. function TranslateString(FromCP, ToCP: Cardinal; Src, Dest: PChar; Length: Integer): Integer;
  332. var
  333. WideCharStr: array[0..1023] of WideChar;
  334. wideBytes: Cardinal;
  335. begin
  336. if Length = -1 then
  337. Length := StrLen(Src);
  338. Result := Length;
  339. if (FromCP = GetOEMCP) and (ToCP = GetACP) then
  340. OemToCharBuff(Src, Dest, Length)
  341. else
  342. if (FromCP = GetACP) and (ToCP = GetOEMCP) then
  343. CharToOemBuff(Src, Dest, Length)
  344. else
  345. if FromCP = ToCP then
  346. begin
  347. if Src <> Dest then
  348. Move(Src^, Dest^, Length);
  349. end else begin
  350. // does this work on Win95/98/ME?
  351. wideBytes := MultiByteToWideChar(FromCP, MB_PRECOMPOSED, Src, Length, LPWSTR(@WideCharStr[0]), 1024);
  352. WideCharToMultiByte(ToCP, 0, LPWSTR(@WideCharStr[0]), wideBytes, Dest, Length, nil, nil);
  353. end;
  354. end;
  355. procedure FindNextName(BaseName: string; var OutName: string; var Modifier: Integer);
  356. var
  357. Extension: string;
  358. begin
  359. Extension := ExtractFileExt(BaseName);
  360. BaseName := Copy(BaseName, 1, Length(BaseName)-Length(Extension));
  361. repeat
  362. Inc(Modifier);
  363. OutName := ChangeFileExt(BaseName+'_'+IntToStr(Modifier), Extension);
  364. until not FileExists(OutName);
  365. end;
  366. {$ifdef FPC}
  367. function MemScan(const Buffer: Pointer; Chr: Byte; Length: Integer): Pointer;
  368. var
  369. I: Integer;
  370. begin
  371. I := System.IndexByte(Buffer, Length, Chr);
  372. if I = -1 then
  373. Result := nil
  374. else
  375. Result := Buffer+I;
  376. end;
  377. {$else}
  378. function MemScan(const Buffer: Pointer; Chr: Byte; Length: Integer): Pointer;
  379. asm
  380. PUSH EDI
  381. MOV EDI,Buffer
  382. MOV AL, Chr
  383. MOV ECX,Length
  384. REPNE SCASB
  385. MOV EAX,0
  386. JNE @@1
  387. MOV EAX,EDI
  388. DEC EAX
  389. @@1: POP EDI
  390. end;
  391. {$endif}
  392. {$ifdef DELPHI_3}
  393. {$ifndef DELPHI_4}
  394. function Min(x, y: integer): integer;
  395. begin
  396. if x < y then
  397. result := x
  398. else
  399. result := y;
  400. end;
  401. function Max(x, y: integer): integer;
  402. begin
  403. if x < y then
  404. result := y
  405. else
  406. result := x;
  407. end;
  408. {$endif}
  409. {$endif}
  410. end.