📄 dbf_parser.pas
字号:
unit dbf_parser;
interface
{$I dbf_common.inc}
uses
SysUtils,
Classes,
{$ifdef KYLIX}
Libc,
{$endif}
{$ifndef WINDOWS}
dbf_wtil,
{$endif}
db,
dbf_prscore,
dbf_common,
dbf_fields,
dbf_prsdef,
dbf_prssupp;
type
TDbfParser = class(TCustomExpressionParser)
private
FDbfFile: Pointer;
FFieldVarList: TStringList;
FIsExpression: Boolean; // expression or simple field?
FFieldType: TExpressionType;
FCaseInsensitive: Boolean;
FRawStringFields: Boolean;
FPartialMatch: boolean;
protected
FCurrentExpression: string;
procedure FillExpressList; override;
procedure HandleUnknownVariable(VarName: string); override;
function GetVariableInfo(VarName: string): TDbfFieldDef;
function CurrentExpression: string; override;
procedure ValidateExpression(AExpression: string); virtual;
function GetResultType: TExpressionType; override;
function GetResultLen: Integer;
procedure SetCaseInsensitive(NewInsensitive: Boolean);
procedure SetRawStringFields(NewRawFields: Boolean);
procedure SetPartialMatch(NewPartialMatch: boolean);
public
constructor Create(ADbfFile: Pointer);
destructor Destroy; override;
procedure ClearExpressions; override;
procedure ParseExpression(AExpression: string); virtual;
function ExtractFromBuffer(Buffer: PChar): PChar; virtual;
property DbfFile: Pointer read FDbfFile write FDbfFile;
property Expression: string read FCurrentExpression;
property ResultLen: Integer read GetResultLen;
property CaseInsensitive: Boolean read FCaseInsensitive write SetCaseInsensitive;
property RawStringFields: Boolean read FRawStringFields write SetRawStringFields;
property PartialMatch: boolean read FPartialMatch write SetPartialMatch;
end;
implementation
uses
dbf,
dbf_dbffile,
dbf_str
{$ifdef WINDOWS}
,Windows
{$endif}
;
type
// TFieldVar aids in retrieving field values from records
// in their proper type
TFieldVar = class(TObject)
private
FFieldDef: TDbfFieldDef;
FDbfFile: TDbfFile;
FFieldName: string;
FExprWord: TExprWord;
protected
function GetFieldVal: Pointer; virtual; abstract;
function GetFieldType: TExpressionType; virtual; abstract;
procedure SetExprWord(NewExprWord: TExprWord); virtual;
property ExprWord: TExprWord read FExprWord write SetExprWord;
public
constructor Create(UseFieldDef: TDbfFieldDef; ADbfFile: TDbfFile);
procedure Refresh(Buffer: PChar); virtual; abstract;
property FieldVal: Pointer read GetFieldVal;
property FieldDef: TDbfFieldDef read FFieldDef;
property FieldType: TExpressionType read GetFieldType;
property DbfFile: TDbfFile read FDbfFile;
property FieldName: string read FFieldName;
end;
TStringFieldVar = class(TFieldVar)
protected
FFieldVal: PChar;
FRawStringField: boolean;
function GetFieldVal: Pointer; override;
function GetFieldType: TExpressionType; override;
procedure SetExprWord(NewExprWord: TExprWord); override;
procedure SetRawStringField(NewRaw: boolean);
procedure UpdateExprWord;
public
constructor Create(UseFieldDef: TDbfFieldDef; ADbfFile: TDbfFile);
destructor Destroy; override;
procedure Refresh(Buffer: PChar); override;
property RawStringField: boolean read FRawStringField write SetRawStringField;
end;
TFloatFieldVar = class(TFieldVar)
private
FFieldVal: Double;
protected
function GetFieldVal: Pointer; override;
function GetFieldType: TExpressionType; override;
public
procedure Refresh(Buffer: PChar); override;
end;
TIntegerFieldVar = class(TFieldVar)
private
FFieldVal: Integer;
protected
function GetFieldVal: Pointer; override;
function GetFieldType: TExpressionType; override;
public
procedure Refresh(Buffer: PChar); override;
end;
{$ifdef SUPPORT_INT64}
TLargeIntFieldVar = class(TFieldVar)
private
FFieldVal: Int64;
protected
function GetFieldVal: Pointer; override;
function GetFieldType: TExpressionType; override;
public
procedure Refresh(Buffer: PChar); override;
end;
{$endif}
TDateTimeFieldVar = class(TFieldVar)
private
FFieldVal: TDateTimeRec;
function GetFieldType: TExpressionType; override;
protected
function GetFieldVal: Pointer; override;
public
procedure Refresh(Buffer: PChar); override;
end;
TBooleanFieldVar = class(TFieldVar)
private
FFieldVal: boolean;
function GetFieldType: TExpressionType; override;
protected
function GetFieldVal: Pointer; override;
public
procedure Refresh(Buffer: PChar); override;
end;
{ TFieldVar }
constructor TFieldVar.Create(UseFieldDef: TDbfFieldDef; ADbfFile: TDbfFile);
begin
inherited Create;
// store field
FFieldDef := UseFieldDef;
FDbfFile := ADbfFile;
FFieldName := UseFieldDef.FieldName;
end;
procedure TFieldVar.SetExprWord(NewExprWord: TExprWord);
begin
FExprWord := NewExprWord;
end;
{ TStringFieldVar }
constructor TStringFieldVar.Create(UseFieldDef: TDbfFieldDef; ADbfFile: TDbfFile);
begin
inherited;
FRawStringField := true;
end;
destructor TStringFieldVar.Destroy;
begin
if not FRawStringField then
FreeMem(FFieldVal);
inherited;
end;
function TStringFieldVar.GetFieldVal: Pointer;
begin
Result := @FFieldVal;
end;
function TStringFieldVar.GetFieldType: TExpressionType;
begin
Result := etString;
end;
procedure TStringFieldVar.Refresh(Buffer: PChar);
var
Len: Integer;
Src: PChar;
begin
Src := Buffer+FieldDef.Offset;
if not FRawStringField then
begin
// copy field data
Len := FieldDef.Size;
while (Len >= 1) and (Src[Len-1] = ' ') do Dec(Len);
// translate to ANSI
Len := TranslateString(DbfFile.UseCodePage, GetACP, Src, FFieldVal, Len);
FFieldVal[Len] := #0;
end else
FFieldVal := Src;
end;
procedure TStringFieldVar.SetExprWord(NewExprWord: TExprWord);
begin
inherited;
UpdateExprWord;
end;
procedure TStringFieldVar.UpdateExprWord;
begin
if FRawStringField then
FExprWord.FixedLen := FieldDef.Size
else
FExprWord.FixedLen := -1;
end;
procedure TStringFieldVar.SetRawStringField(NewRaw: boolean);
begin
if NewRaw = FRawStringField then exit;
FRawStringField := NewRaw;
if NewRaw then
FreeMem(FFieldVal)
else
GetMem(FFieldVal, FieldDef.Size*3+1);
UpdateExprWord;
end;
//--TFloatFieldVar-----------------------------------------------------------
function TFloatFieldVar.GetFieldVal: Pointer;
begin
Result := @FFieldVal;
end;
function TFloatFieldVar.GetFieldType: TExpressionType;
begin
Result := etFloat;
end;
procedure TFloatFieldVar.Refresh(Buffer: PChar);
begin
// database width is default 64-bit double
if not FDbfFile.GetFieldDataFromDef(FieldDef, FieldDef.FieldType, Buffer, @FFieldVal, false) then
FFieldVal := 0.0;
end;
//--TIntegerFieldVar----------------------------------------------------------
function TIntegerFieldVar.GetFieldVal: Pointer;
begin
Result := @FFieldVal;
end;
function TIntegerFieldVar.GetFieldType: TExpressionType;
begin
Result := etInteger;
end;
procedure TIntegerFieldVar.Refresh(Buffer: PChar);
begin
FFieldVal := 0;
FDbfFile.GetFieldDataFromDef(FieldDef, FieldDef.FieldType, Buffer, @FFieldVal, false);
end;
{$ifdef SUPPORT_INT64}
//--TLargeIntFieldVar----------------------------------------------------------
function TLargeIntFieldVar.GetFieldVal: Pointer;
begin
Result := @FFieldVal;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -