Componentes.Terceros.DevExp.../official/x.33/ExpressDataController/Sources/cxDataStorage.pas

2641 lines
73 KiB
ObjectPascal
Raw Permalink Normal View History

{********************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressDataController }
{ }
{ Copyright (c) 1998-2008 Developer Express Inc. }
{ ALL RIGHTS RESERVED }
{ }
{ The entire contents of this file is protected by U.S. and }
{ International Copyright Laws. Unauthorized reproduction, }
{ reverse-engineering, and distribution of all or any portion of }
{ the code contained in this file is strictly prohibited and may }
{ result in severe civil and criminal penalties and will be }
{ prosecuted to the maximum extent possible under the law. }
{ }
{ RESTRICTIONS }
{ }
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
{ LICENSED TO DISTRIBUTE THE EXPRESSDATACONTROLLER AND ALL }
{ ACCOMPANYING VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
{ }
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
{ }
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
{ ADDITIONAL RESTRICTIONS. }
{ }
{********************************************************************}
unit cxDataStorage;
{$I cxVer.inc}
interface
uses
SysUtils, Classes{$IFDEF DELPHI6},Variants
{$IFNDEF NONDB},FMTBcd, SqlTimSt{$ENDIF}{$ENDIF};
type
{$IFNDEF DELPHI6}
PPointer = ^Pointer;
PSmallInt = ^SmallInt;
PInteger = ^Integer;
PWord = ^Word;
PBoolean = ^Boolean;
PDouble =^Double;
PByte = ^Byte;
{$ELSE}
LargeInt = Int64;
PLargeInt = ^LargeInt;
{$ENDIF}
{ Value Types }
PStringValue = PString;
PWideStringValue = PWideString;
TcxValueType = class
protected
class function Compare(P1, P2: Pointer): Integer; virtual;
class procedure FreeBuffer(PBuffer: PChar); virtual;
class procedure FreeTextBuffer(PBuffer: PChar); virtual;
class function GetDataSize: Integer; virtual;
class function GetDataValue(PBuffer: PChar): Variant; virtual;
class function GetDefaultDisplayText(PBuffer: PChar): string; virtual;
class function GetDisplayText(PBuffer: PChar): string; virtual;
class procedure ReadDataValue(PBuffer: PChar; AStream: TStream); virtual;
class procedure ReadDisplayText(PBuffer: PChar; AStream: TStream); virtual;
class procedure SetDataValue(PBuffer: PChar; const Value: Variant); virtual;
class procedure SetDisplayText(PBuffer: PChar; const DisplayText: string); virtual;
class procedure WriteDataValue(PBuffer: PChar; AStream: TStream); virtual;
class procedure WriteDisplayText(PBuffer: PChar; AStream: TStream); virtual;
public
class function Caption: string; virtual;
class function CompareValues(P1, P2: Pointer): Integer; virtual;
class function GetValue(PBuffer: PChar): Variant; virtual;
class function GetVarType: Integer; virtual;
class function IsValueValid(var{const }Value: Variant): Boolean; virtual;
class function IsString: Boolean; virtual;
class procedure PrepareValueBuffer(var PBuffer: PChar); virtual;
end;
TcxValueTypeClass = class of TcxValueType;
TcxStringValueType = class(TcxValueType)
protected
class function Compare(P1, P2: Pointer): Integer; override;
class procedure FreeBuffer(PBuffer: PChar); override;
class function GetDataSize: Integer; override;
class function GetDataValue(PBuffer: PChar): Variant; override;
class procedure ReadDataValue(PBuffer: PChar; AStream: TStream); override;
class procedure SetDataValue(PBuffer: PChar; const Value: Variant); override;
class procedure WriteDataValue(PBuffer: PChar; AStream: TStream); override;
public
class function CompareValues(P1, P2: Pointer): Integer; override;
class function GetValue(PBuffer: PChar): Variant; override;
class function GetVarType: Integer; override;
class function IsString: Boolean; override;
class procedure PrepareValueBuffer(var PBuffer: PChar); override;
end;
TcxWideStringValueType = class(TcxStringValueType)
protected
class function Compare(P1, P2: Pointer): Integer; override;
class procedure FreeBuffer(PBuffer: PChar); override;
class function GetDataSize: Integer; override;
class function GetDataValue(PBuffer: PChar): Variant; override;
class procedure ReadDataValue(PBuffer: PChar; AStream: TStream); override;
class procedure SetDataValue(PBuffer: PChar; const Value: Variant); override;
class procedure WriteDataValue(PBuffer: PChar; AStream: TStream); override;
public
class function CompareValues(P1, P2: Pointer): Integer; override;
class function GetValue(PBuffer: PChar): Variant; override;
class function GetVarType: Integer; override;
class function IsString: Boolean; override;
class procedure PrepareValueBuffer(var PBuffer: PChar); override;
end;
TcxSmallintValueType = class(TcxValueType)
protected
class function GetDataSize: Integer; override;
class function GetDataValue(PBuffer: PChar): Variant; override;
class procedure ReadDataValue(PBuffer: PChar; AStream: TStream); override;
class procedure SetDataValue(PBuffer: PChar; const Value: Variant); override;
class procedure WriteDataValue(PBuffer: PChar; AStream: TStream); override;
public
class function CompareValues(P1, P2: Pointer): Integer; override;
class function GetVarType: Integer; override;
end;
TcxIntegerValueType = class(TcxValueType)
protected
class function GetDataSize: Integer; override;
class function GetDataValue(PBuffer: PChar): Variant; override;
class procedure ReadDataValue(PBuffer: PChar; AStream: TStream); override;
class procedure SetDataValue(PBuffer: PChar; const Value: Variant); override;
class procedure WriteDataValue(PBuffer: PChar; AStream: TStream); override;
public
class function CompareValues(P1, P2: Pointer): Integer; override;
class function GetVarType: Integer; override;
end;
TcxWordValueType = class(TcxValueType)
protected
class function GetDataSize: Integer; override;
class function GetDataValue(PBuffer: PChar): Variant; override;
class procedure ReadDataValue(PBuffer: PChar; AStream: TStream); override;
class procedure SetDataValue(PBuffer: PChar; const Value: Variant); override;
class procedure WriteDataValue(PBuffer: PChar; AStream: TStream); override;
public
class function CompareValues(P1, P2: Pointer): Integer; override;
class function GetVarType: Integer; override;
end;
TcxBooleanValueType = class(TcxValueType)
protected
class function GetDataSize: Integer; override;
class function GetDataValue(PBuffer: PChar): Variant; override;
class function GetDefaultDisplayText(PBuffer: PChar): string; override;
class procedure ReadDataValue(PBuffer: PChar; AStream: TStream); override;
class procedure SetDataValue(PBuffer: PChar; const Value: Variant); override;
class procedure WriteDataValue(PBuffer: PChar; AStream: TStream); override;
public
class function CompareValues(P1, P2: Pointer): Integer; override;
class function GetVarType: Integer; override;
end;
TcxFloatValueType = class(TcxValueType) // TODO: Double or Extended?
protected
class function GetDataSize: Integer; override;
class function GetDataValue(PBuffer: PChar): Variant; override;
class procedure ReadDataValue(PBuffer: PChar; AStream: TStream); override;
class procedure SetDataValue(PBuffer: PChar; const Value: Variant); override;
class procedure WriteDataValue(PBuffer: PChar; AStream: TStream); override;
public
class function CompareValues(P1, P2: Pointer): Integer; override;
class function GetVarType: Integer; override;
end;
TcxCurrencyValueType = class(TcxValueType)
protected
class function GetDataSize: Integer; override;
class function GetDataValue(PBuffer: PChar): Variant; override;
class procedure ReadDataValue(PBuffer: PChar; AStream: TStream); override;
class procedure SetDataValue(PBuffer: PChar; const Value: Variant); override;
class procedure WriteDataValue(PBuffer: PChar; AStream: TStream); override;
public
class function CompareValues(P1, P2: Pointer): Integer; override;
class function GetVarType: Integer; override;
end;
TcxDateTimeValueType = class(TcxValueType)
private
class function GetDateTime(PBuffer: PChar): TDateTime;
protected
class function GetDataSize: Integer; override;
class function GetDataValue(PBuffer: PChar): Variant; override;
class function GetDefaultDisplayText(PBuffer: PChar): string; override;
class procedure ReadDataValue(PBuffer: PChar; AStream: TStream); override;
class procedure SetDataValue(PBuffer: PChar; const Value: Variant); override;
class procedure WriteDataValue(PBuffer: PChar; AStream: TStream); override;
public
class function CompareValues(P1, P2: Pointer): Integer; override;
class function GetVarType: Integer; override;
end;
{$IFDEF DELPHI6}
TcxLargeIntValueType = class(TcxValueType)
protected
class function GetDataSize: Integer; override;
class function GetDataValue(PBuffer: PChar): Variant; override;
class procedure ReadDataValue(PBuffer: PChar; AStream: TStream); override;
class procedure SetDataValue(PBuffer: PChar; const Value: Variant); override;
class procedure WriteDataValue(PBuffer: PChar; AStream: TStream); override;
public
class function CompareValues(P1, P2: Pointer): Integer; override;
class function GetVarType: Integer; override;
end;
{$IFNDEF NONDB}
TcxFMTBcdValueType = class(TcxValueType)
protected
class function GetDataSize: Integer; override;
class function GetDataValue(PBuffer: PChar): Variant; override;
class function GetDefaultDisplayText(PBuffer: PChar): string; override;
class procedure SetDataValue(PBuffer: PChar; const Value: Variant); override;
public
class function CompareValues(P1, P2: Pointer): Integer; override;
class function GetVarType: Integer; override;
end;
TcxSQLTimeStampValueType = class(TcxValueType)
protected
class function GetDataSize: Integer; override;
class function GetDataValue(PBuffer: PChar): Variant; override;
class procedure SetDataValue(PBuffer: PChar; const Value: Variant); override;
public
class function CompareValues(P1, P2: Pointer): Integer; override;
class function GetVarType: Integer; override;
end;
{$ENDIF}
{$ENDIF}
TcxVariantValueType = class(TcxValueType)
protected
class function Compare(P1, P2: Pointer): Integer; override;
class procedure FreeBuffer(PBuffer: PChar); override;
class function GetDataSize: Integer; override;
class function GetDataValue(PBuffer: PChar): Variant; override;
class procedure SetDataValue(PBuffer: PChar; const Value: Variant); override;
public
class function CompareValues(P1, P2: Pointer): Integer; override;
class function GetValue(PBuffer: PChar): Variant; override;
class procedure PrepareValueBuffer(var PBuffer: PChar); override;
end;
TcxObjectValueType = class(TcxIntegerValueType)
protected
class procedure FreeBuffer(PBuffer: PChar); override;
class procedure ReadDataValue(PBuffer: PChar; AStream: TStream); override;
class procedure SetDataValue(PBuffer: PChar; const Value: Variant); override;
class procedure WriteDataValue(PBuffer: PChar; AStream: TStream); override;
end;
{ TcxDataStorage }
TcxDataStorage = class;
TcxValueDefs = class;
TcxValueDef = class
private
FBufferSize: Integer;
FDataSize: Integer;
FStored: Boolean;
FLinkObject: TObject;
FOffset: Integer;
FStreamStored: Boolean;
FTextStored: Boolean;
FValueDefs: TcxValueDefs;
FValueTypeClass: TcxValueTypeClass;
function GetIsNeedConversion: Boolean;
function GetTextStored: Boolean;
procedure SetStored(Value: Boolean);
procedure SetTextStored(Value: Boolean);
procedure SetValueTypeClass(Value: TcxValueTypeClass);
protected
procedure Changed(AResyncNeeded: Boolean);
function Compare(P1, P2: PChar): Integer;
procedure FreeBuffer(PBuffer: PChar);
procedure FreeTextBuffer(PBuffer: PChar);
function GetDataValue(PBuffer: PChar): Variant;
function GetDisplayText(PBuffer: PChar): string;
function GetLinkObject: TObject; virtual;
function GetStored: Boolean; virtual;
procedure Init(var AOffset: Integer);
function IsNullValue(PBuffer: PChar): Boolean;
function IsNullValueEx(PBuffer: PChar; AOffset: Integer): Boolean;
procedure ReadDataValue(PBuffer: PChar; AStream: TStream);
procedure ReadDisplayText(PBuffer: PChar; AStream: TStream);
procedure SetDataValue(PBuffer: PChar; const Value: Variant);
procedure SetDisplayText(PBuffer: PChar; const DisplayText: string);
procedure SetLinkObject(Value: TObject); virtual;
procedure SetNull(PBuffer: PChar; IsNull: Boolean);
procedure WriteDataValue(PBuffer: PChar; AStream: TStream);
procedure WriteDisplayText(PBuffer: PChar; AStream: TStream);
property BufferSize: Integer read FBufferSize;
property DataSize: Integer read FDataSize;
property Offset: Integer read FOffset;
property ValueDefs: TcxValueDefs read FValueDefs;
public
constructor Create(AValueDefs: TcxValueDefs; AValueTypeClass: TcxValueTypeClass); virtual;
destructor Destroy; override;
procedure Assign(ASource: TcxValueDef); virtual;
function CompareValues(AIsNull1, AIsNull2: Boolean; P1, P2: PChar): Integer;
property IsNeedConversion: Boolean read GetIsNeedConversion;
property LinkObject: TObject read GetLinkObject write SetLinkObject;
property Stored: Boolean read GetStored write SetStored default True;
property TextStored: Boolean read GetTextStored write SetTextStored default False;
property ValueTypeClass: TcxValueTypeClass read FValueTypeClass write SetValueTypeClass;
property StreamStored: Boolean read FStreamStored write FStreamStored default True;
end;
TcxValueDefClass = class of TcxValueDef;
TcxValueDefs = class
private
FDataStorage: TcxDataStorage;
FItems: TList;
FRecordOffset: Integer;
FRecordSize: Integer;
function GetStoredCount: Integer;
function GetCount: Integer;
function GetItem(Index: Integer): TcxValueDef;
protected
procedure Changed(AValueDef: TcxValueDef; AResyncNeeded: Boolean); virtual;
function GetValueDefClass: TcxValueDefClass; virtual;
procedure Prepare(AStartOffset: Integer); virtual;
procedure Remove(AItem: TcxValueDef);
property DataStorage: TcxDataStorage read FDataStorage;
public
constructor Create(ADataStorage: TcxDataStorage); virtual;
destructor Destroy; override;
function Add(AValueTypeClass: TcxValueTypeClass; AStored, ATextStored: Boolean; ALinkObject: TObject): TcxValueDef;
procedure Clear;
property StoredCount: Integer read GetStoredCount;
property Count: Integer read GetCount;
property Items[Index: Integer]: TcxValueDef read GetItem; default;
property RecordSize: Integer read FRecordSize;
end;
{ internal value defs }
TcxInternalValueDef = class(TcxValueDef)
protected
function GetLinkObject: TObject; override;
function GetStored: Boolean; override;
public
function GetValueDef: TcxValueDef;
end;
TcxInternalValueDefs = class(TcxValueDefs)
protected
function GetValueDefClass: TcxValueDefClass; override;
public
function FindByLinkObject(ALinkObject: TObject): TcxValueDef;
procedure RemoveByLinkObject(ALinkObject: TObject);
end;
TcxValueDefReader = class
public
constructor Create; virtual;
function GetDisplayText(AValueDef: TcxValueDef): string; virtual;
function GetValue(AValueDef: TcxValueDef): Variant; virtual;
function IsInternal(AValueDef: TcxValueDef): Boolean; virtual;
end;
TcxValueDefReaderClass = class of TcxValueDefReader;
TcxValueDefSetProc = procedure (AValueDef: TcxValueDef; AFromRecordIndex, AToRecordIndex: Integer;
AValueDefReader: TcxValueDefReader) of object;
TcxDataStorage = class
private
FDestroying: Boolean;
FInternalRecordBuffers: TList;
FInternalValueDefs: TcxInternalValueDefs;
FStoredValuesOnly: Boolean;
FRecordBuffers: TList;
FRecordIDCounter: Integer;
FUseRecordID: Boolean;
FValueDefs: TcxValueDefs;
FValueDefsList: TList;
// FValueDefsChanged: Boolean;
FOnClearInternalRecords: TNotifyEvent;
function GetRecordBuffer(Index: Integer): PChar;
function GetRecordCount: Integer;
procedure SetStoredValuesOnly(Value: Boolean);
procedure SetRecordBuffer(Index: Integer; Value: PChar);
procedure SetRecordCount(Value: Integer);
procedure SetUseRecordID(Value: Boolean);
protected
function AllocRecordBuffer(Index: Integer): PChar;
function CalcRecordOffset: Integer;
procedure ChangeRecordFlag(PBuffer: PChar; AFlag: Byte; ATurnOn: Boolean);
procedure CheckRecordID(ARecordIndex: Integer);
procedure CheckRecordIDCounter;
procedure CheckRecordIDCounterAfterLoad(ALoadedID: Integer);
function CheckValueDef(ARecordIndex: Integer; var AValueDef: TcxValueDef): Boolean;
procedure DeleteInternalRecord(ARecordIndex: Integer);
procedure FreeAndNilRecordBuffer(AIndex: Integer);
procedure InitStructure(AValueDefs: TcxValueDefs); virtual;
procedure InsertValueDef(AIndex: Integer; AValueDef: TcxValueDef);
function IsRecordFlag(PBuffer: PChar; AFlag: Byte): Boolean;
procedure RemoveValueDef(AValueDef: TcxValueDef);
procedure ValueDefsChanged(AValueDef: TcxValueDef; AResyncNeeded: Boolean); virtual;
function ValueDefsByRecordIndex(Index: Integer): TcxValueDefs; virtual;
property InternalValueDefs: TcxInternalValueDefs read FInternalValueDefs;
public
constructor Create; virtual;
destructor Destroy; override;
function AddInternalRecord: Integer;
function AppendRecord: Integer;
procedure BeforeDestruction; override;
procedure BeginLoad;
procedure CheckStructure;
procedure Clear(AWithoutInternal: Boolean);
procedure ClearInternalRecords;
procedure ClearRecords(AClearList: Boolean);
function CompareRecords(ARecordIndex1, ARecordIndex2: Integer; AValueDef: TcxValueDef): Integer;
procedure DeleteRecord(ARecordIndex: Integer);
procedure EndLoad;
function GetDisplayText(ARecordIndex: Integer; AValueDef: TcxValueDef): string;
function GetCompareInfo(ARecordIndex: Integer; AValueDef: TcxValueDef; var P: PChar): Boolean;
function GetRecordID(ARecordIndex: Integer): Integer;
function GetValue(ARecordIndex: Integer; AValueDef: TcxValueDef): Variant;
procedure InsertRecord(ARecordIndex: Integer);
procedure ReadData(ARecordIndex: Integer; AStream: TStream);
procedure ReadRecord(ARecordIndex: Integer; AValueDefReader: TcxValueDefReader);
procedure ReadRecordFrom(AFromRecordIndex, AToRecordIndex: Integer; AValueDefReader: TcxValueDefReader; ASetProc: TcxValueDefSetProc);
procedure SetDisplayText(ARecordIndex: Integer; AValueDef: TcxValueDef; const Value: string);
procedure SetRecordID(ARecordIndex, AID: Integer);
procedure SetValue(ARecordIndex: Integer; AValueDef: TcxValueDef; const Value: Variant);
procedure WriteData(ARecordIndex: Integer; AStream: TStream);
procedure BeginStreaming(ACompare: TListSortCompare);
procedure EndStreaming;
property StoredValuesOnly: Boolean read FStoredValuesOnly write SetStoredValuesOnly;
property UseRecordID: Boolean read FUseRecordID write SetUseRecordID;
property RecordBuffers[Index: Integer]: PChar read GetRecordBuffer write SetRecordBuffer;
property RecordCount: Integer read GetRecordCount write SetRecordCount;
property ValueDefs: TcxValueDefs read FValueDefs;
property OnClearInternalRecords: TNotifyEvent read FOnClearInternalRecords write FOnClearInternalRecords;
end;
{ TcxLookupList }
TcxLookupListItem = record
KeyValue: Variant;
DisplayText: string;
end;
PcxLookupListItem = ^TcxLookupListItem;
TcxLookupList = class
private
FItems: TList;
function GetCount: Integer;
function GetItem(Index: Integer): PcxLookupListItem;
public
constructor Create;
destructor Destroy; override;
procedure Clear;
function Find(const AKeyValue: Variant; var AIndex: Integer): Boolean;
procedure Insert(AIndex: Integer; const AKeyValue: Variant; const ADisplayText: string);
property Count: Integer read GetCount;
property Items[Index: Integer]: PcxLookupListItem read GetItem; default;
end;
{ TcxValueTypeClassList }
TcxValueTypeClassList = class
private
FItems: TList;
function GetCount: Integer;
function GetItem(Index: Integer): TcxValueTypeClass;
public
constructor Create;
destructor Destroy; override;
function ItemByCaption(const ACaption: string): TcxValueTypeClass;
procedure RegisterItem(AValueTypeClass: TcxValueTypeClass);
procedure UnregisterItem(AValueTypeClass: TcxValueTypeClass);
property Count: Integer read GetCount;
property Items[Index: Integer]: TcxValueTypeClass read GetItem; default;
end;
function cxValueTypeClassList: TcxValueTypeClassList;
function IsDateTimeValueTypeClass(AValueTypeClass: TcxValueTypeClass): Boolean;
implementation
uses
cxVariants;
const
RecordFlagSize = SizeOf(Byte);
ValueFlagSize = SizeOf(Byte);
PointerSize = SizeOf(Pointer);
RecordIDSize = SizeOf(Integer);
// RecordFlag Bit Masks
RecordFlag_Busy = $01;
var
FValueTypeClassList: TcxValueTypeClassList;
function cxValueTypeClassList: TcxValueTypeClassList;
begin
if FValueTypeClassList = nil then
FValueTypeClassList := TcxValueTypeClassList.Create;
Result := FValueTypeClassList;
end;
function IsDateTimeValueTypeClass(AValueTypeClass: TcxValueTypeClass): Boolean;
begin
Result := (AValueTypeClass = TcxDateTimeValueType)
{$IFDEF DELPHI6}{$IFNDEF NONDB} or (AValueTypeClass = TcxSQLTimeStampValueType){$ENDIF}{$ENDIF};
end;
function IncPChar(P: PChar; AOffset: Integer): PChar;
begin
Result := P + AOffset;
end;
{ TcxValueType }
class function TcxValueType.Caption: string;
var
I: Integer;
begin
Result := ClassName;
if Result <> '' then
begin
if Copy(Result, 1, 3) = 'Tcx' then
Delete(Result, 1, 3);
I := Pos('ValueType', Result);
if I <> 0 then
Delete(Result, I, Length('ValueType'));
end;
end;
class function TcxValueType.CompareValues(P1, P2: Pointer): Integer;
begin
Result := VarCompare(GetDataValue(P1), GetDataValue(P2));
end;
class function TcxValueType.GetValue(PBuffer: PChar): Variant;
begin
Result := GetDataValue(PBuffer);
end;
class function TcxValueType.GetVarType: Integer;
begin
Result := varVariant;
end;
class function TcxValueType.IsValueValid(var{const }Value: Variant): Boolean;
//var
// V: Variant;
begin
if VarIsNull(Value) or (GetVarType = varVariant) then // not Empty?
Result := True
else
begin
Result := False;
try
VarCast(Value{V}, Value, GetVarType);
Result := True;
except
on E: EVariantError do;
end;
end;
end;
class function TcxValueType.IsString: Boolean;
begin
Result := False;
end;
class procedure TcxValueType.PrepareValueBuffer(var PBuffer: PChar);
begin
end;
class function TcxValueType.Compare(P1, P2: Pointer): Integer;
begin
Result := CompareValues(P1, P2);
end;
class procedure TcxValueType.FreeBuffer(PBuffer: PChar);
begin
end;
class procedure TcxValueType.FreeTextBuffer(PBuffer: PChar);
var
P: PStringValue;
begin
P := PPointer(PBuffer)^;
if P <> nil then
Dispose(P);
end;
class function TcxValueType.GetDataSize: Integer;
begin
Result := 0;
end;
class function TcxValueType.GetDataValue(PBuffer: PChar): Variant;
begin
Result := Null;
end;
class function TcxValueType.GetDefaultDisplayText(PBuffer: PChar): string;
begin
try
Result := VarToStr(GetDataValue(PBuffer));
except
on EVariantError do
Result := '';
end;
end;
class function TcxValueType.GetDisplayText(PBuffer: PChar): string;
var
P: PStringValue;
begin
P := PPointer(PBuffer)^;
if P <> nil then
Result := P^
else
Result := '';
end;
class procedure TcxValueType.ReadDataValue(PBuffer: PChar; AStream: TStream);
begin
SetDataValue(PBuffer, ReadVariantFunc(AStream));
end;
class procedure TcxValueType.ReadDisplayText(PBuffer: PChar; AStream: TStream);
begin
SetDisplayText(PBuffer, ReadStringFunc(AStream));
end;
class procedure TcxValueType.SetDataValue(PBuffer: PChar; const Value: Variant);
begin
end;
class procedure TcxValueType.SetDisplayText(PBuffer: PChar; const DisplayText: string);
var
P: PStringValue;
begin
P := PPointer(PBuffer)^;
if P = nil then
begin
New(P);
PPointer(PBuffer)^ := P;
end;
P^ := DisplayText;
end;
class procedure TcxValueType.WriteDataValue(PBuffer: PChar; AStream: TStream);
begin
WriteVariantProc(AStream, GetDataValue(PBuffer));
end;
class procedure TcxValueType.WriteDisplayText(PBuffer: PChar; AStream: TStream);
begin
WriteStringProc(AStream, GetDisplayText(PBuffer));
end;
{ TcxStringValueType }
class function TcxStringValueType.CompareValues(P1, P2: Pointer): Integer;
var
S1, S2: string;
begin
if Assigned(P1) then
begin
if Assigned(P2) then
begin
S1 := PStringValue(P1)^;
S2 := PStringValue(P2)^;
if S1 = S2 then
Result := 0
else
if S1 < S2 then
Result := -1
else
Result := 1;
end
else
Result := 1;
end
else
begin
if Assigned(P2) then
Result := -1
else
Result := 0;
end;
end;
class function TcxStringValueType.GetValue(PBuffer: PChar): Variant;
begin
Result := GetDataValue(@PBuffer);
end;
class function TcxStringValueType.GetVarType: Integer;
begin
Result := varString;
end;
class function TcxStringValueType.IsString: Boolean;
begin
Result := True;
end;
class procedure TcxStringValueType.PrepareValueBuffer(var PBuffer: PChar);
begin
PBuffer := PPointer(PBuffer)^;
end;
class function TcxStringValueType.Compare(P1, P2: Pointer): Integer;
begin
Result := CompareValues(PPointer(P1)^, PPointer(P2)^);
end;
class procedure TcxStringValueType.FreeBuffer(PBuffer: PChar);
begin
Dispose(PStringValue(PPointer(PBuffer)^));
end;
class function TcxStringValueType.GetDataSize: Integer;
begin
Result := SizeOf(PStringValue);
end;
class function TcxStringValueType.GetDataValue(PBuffer: PChar): Variant;
var
P: PStringValue;
begin
P := PPointer(PBuffer)^;
if P <> nil then
Result := P^
else
Result := inherited GetDataValue(PBuffer);
end;
class procedure TcxStringValueType.ReadDataValue(PBuffer: PChar; AStream: TStream);
begin
SetDataValue(PBuffer, ReadStringFunc(AStream));
end;
class procedure TcxStringValueType.SetDataValue(PBuffer: PChar; const Value: Variant);
begin
SetDisplayText(PBuffer, Value);
end;
class procedure TcxStringValueType.WriteDataValue(PBuffer: PChar; AStream: TStream);
begin
WriteStringProc(AStream, GetDisplayText(PBuffer));
end;
{ TcxWideStringValueType }
class function TcxWideStringValueType.CompareValues(P1, P2: Pointer): Integer;
var
WS1, WS2: WideString;
begin
if Assigned(P1) then
begin
if Assigned(P2) then
begin
WS1 := PWideStringValue(P1)^;
WS2 := PWideStringValue(P2)^;
if WS1 = WS2 then
Result := 0
else
if WS1 < WS2 then
Result := -1
else
Result := 1;
end
else
Result := 1;
end
else
begin
if Assigned(P2) then
Result := -1
else
Result := 0;
end;
end;
class function TcxWideStringValueType.GetValue(PBuffer: PChar): Variant;
begin
Result := GetDataValue(@PBuffer);
end;
class function TcxWideStringValueType.GetVarType: Integer;
begin
Result := varOleStr;
end;
class function TcxWideStringValueType.IsString: Boolean;
begin
Result := True;
end;
class procedure TcxWideStringValueType.PrepareValueBuffer(var PBuffer: PChar);
begin
PBuffer := PPointer(PBuffer)^;
end;
class function TcxWideStringValueType.Compare(P1, P2: Pointer): Integer;
begin
Result := CompareValues(PPointer(P1)^, PPointer(P2)^);
end;
class procedure TcxWideStringValueType.FreeBuffer(PBuffer: PChar);
begin
Dispose(PWideStringValue(PPointer(PBuffer)^));
end;
class function TcxWideStringValueType.GetDataSize: Integer;
begin
Result := SizeOf(PWideStringValue);
end;
class function TcxWideStringValueType.GetDataValue(PBuffer: PChar): Variant;
var
P: PWideStringValue;
begin
P := PPointer(PBuffer)^;
if P <> nil then
Result := P^
else
Result := inherited GetDataValue(PBuffer);
end;
class procedure TcxWideStringValueType.ReadDataValue(PBuffer: PChar; AStream: TStream);
begin
SetDataValue(PBuffer, ReadWideStringFunc(AStream));
end;
class procedure TcxWideStringValueType.SetDataValue(PBuffer: PChar; const Value: Variant);
var
P: PWideStringValue;
begin
P := PPointer(PBuffer)^;
if P = nil then
begin
New(P);
PPointer(PBuffer)^ := P;
end;
P^ := Value;
end;
class procedure TcxWideStringValueType.WriteDataValue(PBuffer: PChar; AStream: TStream);
begin
WriteWideStringProc(AStream, VarToStr(GetDataValue(PBuffer)));
end;
{ TcxSmallintValueType }
class function TcxSmallintValueType.CompareValues(P1, P2: Pointer): Integer;
begin
Result := PSmallInt(P1)^ - PSmallInt(P2)^;
end;
class function TcxSmallintValueType.GetVarType: Integer;
begin
Result := varSmallint;
end;
class function TcxSmallintValueType.GetDataSize: Integer;
begin
Result := SizeOf(SmallInt);
end;
class function TcxSmallintValueType.GetDataValue(PBuffer: PChar): Variant;
begin
Result := PSmallInt(PBuffer)^;
end;
class procedure TcxSmallintValueType.ReadDataValue(PBuffer: PChar; AStream: TStream);
begin
SetDataValue(PBuffer, ReadSmallIntFunc(AStream));
end;
class procedure TcxSmallintValueType.SetDataValue(PBuffer: PChar; const Value: Variant);
begin
PSmallInt(PBuffer)^ := Value;
end;
class procedure TcxSmallintValueType.WriteDataValue(PBuffer: PChar; AStream: TStream);
begin
WriteSmallIntProc(AStream, SmallInt(GetDataValue(PBuffer)));
end;
{ TcxIntegerValueType }
class function TcxIntegerValueType.CompareValues(P1, P2: Pointer): Integer;
begin
Result := PInteger(P1)^ - PInteger(P2)^;
end;
class function TcxIntegerValueType.GetVarType: Integer;
begin
Result := varInteger;
end;
class function TcxIntegerValueType.GetDataSize: Integer;
begin
Result := SizeOf(Integer);
end;
class function TcxIntegerValueType.GetDataValue(PBuffer: PChar): Variant;
begin
Result := PInteger(PBuffer)^;
end;
class procedure TcxIntegerValueType.ReadDataValue(PBuffer: PChar; AStream: TStream);
begin
SetDataValue(PBuffer, ReadIntegerFunc(AStream));
end;
class procedure TcxIntegerValueType.SetDataValue(PBuffer: PChar; const Value: Variant);
begin
PInteger(PBuffer)^ := Value;
end;
class procedure TcxIntegerValueType.WriteDataValue(PBuffer: PChar; AStream: TStream);
begin
WriteIntegerProc(AStream, Integer(GetDataValue(PBuffer)));
end;
{ TcxWordValueType }
class function TcxWordValueType.CompareValues(P1, P2: Pointer): Integer;
begin
Result := PWord(P1)^ - PWord(P2)^;
end;
class function TcxWordValueType.GetVarType: Integer;
begin
Result := {$IFDEF DELPHI6}varWord{$ELSE}$0012{$ENDIF};
end;
class function TcxWordValueType.GetDataSize: Integer;
begin
Result := SizeOf(Word);
end;
class function TcxWordValueType.GetDataValue(PBuffer: PChar): Variant;
begin
Result := PWord(PBuffer)^;
end;
class procedure TcxWordValueType.ReadDataValue(PBuffer: PChar; AStream: TStream);
begin
SetDataValue(PBuffer, ReadWordFunc(AStream));
end;
class procedure TcxWordValueType.SetDataValue(PBuffer: PChar; const Value: Variant);
begin
PWord(PBuffer)^ := Value;
end;
class procedure TcxWordValueType.WriteDataValue(PBuffer: PChar; AStream: TStream);
begin
WriteWordProc(AStream, Word(GetDataValue(PBuffer)));
end;
{ TcxBooleanValueType }
class function TcxBooleanValueType.CompareValues(P1, P2: Pointer): Integer;
begin
Result := Integer(PBoolean(P1)^) - Integer(PBoolean(P2)^);
end;
class function TcxBooleanValueType.GetVarType: Integer;
begin
Result := varBoolean;
end;
class function TcxBooleanValueType.GetDataSize: Integer;
begin
Result := SizeOf(Boolean);
end;
class function TcxBooleanValueType.GetDataValue(PBuffer: PChar): Variant;
begin
Result := PBoolean(PBuffer)^;
end;
class function TcxBooleanValueType.GetDefaultDisplayText(PBuffer: PChar): string;
begin
try
{$IFDEF DELPHI6}
Result := BoolToStr(GetDataValue(PBuffer), True);
{$ELSE}
Result := GetDataValue(PBuffer);
{$ENDIF}
except
on EVariantError do
Result := '';
end;
end;
class procedure TcxBooleanValueType.ReadDataValue(PBuffer: PChar; AStream: TStream);
begin
SetDataValue(PBuffer, ReadBooleanFunc(AStream));
end;
class procedure TcxBooleanValueType.SetDataValue(PBuffer: PChar; const Value: Variant);
begin
PBoolean(PBuffer)^ := Value;
end;
class procedure TcxBooleanValueType.WriteDataValue(PBuffer: PChar; AStream: TStream);
begin
WriteBooleanProc(AStream, Boolean(GetDataValue(PBuffer)));
end;
{ TcxFloatValueType }
class function TcxFloatValueType.CompareValues(P1, P2: Pointer): Integer;
var
D1, D2: Double;
begin
D1 := PDouble(P1)^;
D2 := PDouble(P2)^;
if D1 = D2 then
Result := 0
else
if D1 < D2 then
Result := -1
else
Result := 1;
end;
class function TcxFloatValueType.GetVarType: Integer;
begin
Result := varDouble;
end;
class function TcxFloatValueType.GetDataSize: Integer;
begin
Result := SizeOf(Double);
end;
class function TcxFloatValueType.GetDataValue(PBuffer: PChar): Variant;
begin
Result := PDouble(PBuffer)^;
end;
class procedure TcxFloatValueType.ReadDataValue(PBuffer: PChar; AStream: TStream);
var
E: Extended;
begin
ReadFloatProc(AStream, E);
PDouble(PBuffer)^ := E;
end;
class procedure TcxFloatValueType.SetDataValue(PBuffer: PChar; const Value: Variant);
begin
PDouble(PBuffer)^ := Value;
end;
class procedure TcxFloatValueType.WriteDataValue(PBuffer: PChar; AStream: TStream);
begin
WriteFloatProc(AStream, Double(GetDataValue(PBuffer)));
end;
{ TcxCurrencyValueType }
class function TcxCurrencyValueType.CompareValues(P1, P2: Pointer): Integer;
var
C1, C2: Currency;
begin
C1 := PCurrency(P1)^;
C2 := PCurrency(P2)^;
if C1 = C2 then
Result := 0
else
if C1 < C2 then
Result := -1
else
Result := 1;
end;
class function TcxCurrencyValueType.GetVarType: Integer;
begin
Result := varCurrency;
end;
class function TcxCurrencyValueType.GetDataSize: Integer;
begin
Result := SizeOf(Currency);
end;
class function TcxCurrencyValueType.GetDataValue(PBuffer: PChar): Variant;
begin
Result := PCurrency(PBuffer)^;
end;
class procedure TcxCurrencyValueType.ReadDataValue(PBuffer: PChar; AStream: TStream);
begin
SetDataValue(PBuffer, ReadCurrencyFunc(AStream));
end;
class procedure TcxCurrencyValueType.SetDataValue(PBuffer: PChar; const Value: Variant);
begin
PCurrency(PBuffer)^ := Value;
end;
class procedure TcxCurrencyValueType.WriteDataValue(PBuffer: PChar; AStream: TStream);
begin
WriteCurrencyProc(AStream, Currency(GetDataValue(PBuffer)));
end;
{ TcxDateTimeValueType }
class function TcxDateTimeValueType.CompareValues(P1, P2: Pointer): Integer;
var
D1, D2: Double;
begin
D1 := PDateTime(P1)^;
D2 := PDateTime(P2)^;
if D1 = D2 then
Result := 0
else
if D1 < D2 then
Result := -1
else
Result := 1;
end;
class function TcxDateTimeValueType.GetVarType: Integer;
begin
Result := varDate;
end;
class function TcxDateTimeValueType.GetDataSize: Integer;
begin
Result := SizeOf(TDateTime);
end;
class function TcxDateTimeValueType.GetDataValue(PBuffer: PChar): Variant;
begin
Result := GetDateTime(PBuffer);
end;
class function TcxDateTimeValueType.GetDefaultDisplayText(PBuffer: PChar): string;
var
DT: TDateTime;
begin
DT := GetDateTime(PBuffer);
try
Result := VarToStr(DT);
except
on EVariantError do
Result := DateTimeToStr(DT);
end;
end;
class procedure TcxDateTimeValueType.ReadDataValue(PBuffer: PChar; AStream: TStream);
begin
SetDataValue(PBuffer, ReadDateTimeFunc(AStream));
end;
class procedure TcxDateTimeValueType.SetDataValue(PBuffer: PChar; const Value: Variant);
begin
PDateTime(PBuffer)^ := VarToDateTime(Value);
end;
class procedure TcxDateTimeValueType.WriteDataValue(PBuffer: PChar; AStream: TStream);
begin
WriteDateTimeProc(AStream, TDateTime(GetDataValue(PBuffer)));
end;
class function TcxDateTimeValueType.GetDateTime(PBuffer: PChar): TDateTime;
begin
Result := PDateTime(PBuffer)^;
end;
{$IFDEF DELPHI6}
{ TcxLargeIntValueType }
class function TcxLargeIntValueType.CompareValues(P1, P2: Pointer): Integer;
var
L1, L2: LargeInt;
begin
L1 := PLargeInt(P1)^;
L2 := PLargeInt(P2)^;
if L1 = L2 then
Result := 0
else
if L1 < L2 then
Result := -1
else
Result := 1;
end;
class function TcxLargeIntValueType.GetVarType: Integer;
begin
Result := varInt64;
end;
class function TcxLargeIntValueType.GetDataSize: Integer;
begin
Result := SizeOf(LargeInt);
end;
class function TcxLargeIntValueType.GetDataValue(PBuffer: PChar): Variant;
begin
Result := PLargeInt(PBuffer)^;
end;
class procedure TcxLargeIntValueType.ReadDataValue(PBuffer: PChar; AStream: TStream);
begin
SetDataValue(PBuffer, ReadLargeIntFunc(AStream));
end;
class procedure TcxLargeIntValueType.SetDataValue(PBuffer: PChar; const Value: Variant);
begin
PLargeInt(PBuffer)^ := Value;
end;
class procedure TcxLargeIntValueType.WriteDataValue(PBuffer: PChar; AStream: TStream);
begin
WriteLargeIntProc(AStream, PLargeInt(PBuffer)^);
end;
{$IFNDEF NONDB}
{ TcxFMTBcdValueType }
class function TcxFMTBcdValueType.CompareValues(P1, P2: Pointer): Integer;
var
B1, B2: TBcd;
begin
B1 := PBcd(P1)^;
B2 := PBcd(P2)^;
Result := BcdCompare(B1, B2);
end;
class function TcxFMTBcdValueType.GetVarType: Integer;
begin
Result := VarFMTBcd;
end;
class function TcxFMTBcdValueType.GetDataSize: Integer;
begin
Result := SizeOf(TBcd);
end;
class function TcxFMTBcdValueType.GetDataValue(PBuffer: PChar): Variant;
begin
Result := VarFMTBcdCreate(PBcd(PBuffer)^);
// Result := BcdToDouble(PBcd(PBuffer)^);
end;
class function TcxFMTBcdValueType.GetDefaultDisplayText(PBuffer: PChar): string;
var
Bcd: TBcd;
begin
Bcd := PBcd(PBuffer)^;
Result := BcdToStrF(Bcd, ffGeneral, 0, 0); // P, D - ignored in BcdToStrF
end;
class procedure TcxFMTBcdValueType.SetDataValue(PBuffer: PChar; const Value: Variant);
begin
PBcd(PBuffer)^ := VarToBcd(Value);
end;
{ TcxSQLTimeStampValueType }
class function TcxSQLTimeStampValueType.CompareValues(P1, P2: Pointer): Integer;
var
T1, T2: TSQLTimeStamp;
begin
T1 := PSQLTimeStamp(P1)^;
T2 := PSQLTimeStamp(P2)^;
Result := T1.Year - T2.Year;
if Result = 0 then
begin
Result := T1.Month - T2.Month;
if Result = 0 then
begin
Result := T1.Day - T2.Day;
if Result = 0 then
begin
Result := T1.Hour - T2.Hour;
if Result = 0 then
begin
Result := T1.Minute - T2.Minute;
if Result = 0 then
begin
Result := T1.Second - T2.Second;
if Result = 0 then
Result := T1.Fractions - T2.Fractions;
end;
end;
end;
end;
end;
end;
class function TcxSQLTimeStampValueType.GetVarType: Integer;
begin
Result := VarSQLTimeStamp;
end;
class function TcxSQLTimeStampValueType.GetDataSize: Integer;
begin
Result := SizeOf(TSQLTimeStamp);
end;
class function TcxSQLTimeStampValueType.GetDataValue(PBuffer: PChar): Variant;
begin
Result := SQLTimeStampToDateTime(PSQLTimeStamp(PBuffer)^);
end;
class procedure TcxSQLTimeStampValueType.SetDataValue(PBuffer: PChar; const Value: Variant);
begin
PSQLTimeStamp(PBuffer)^ := VarToSQLTimeStamp(Value);
end;
{$ENDIF}
{$ENDIF}
{ TcxVariantValueType }
class function TcxVariantValueType.CompareValues(P1, P2: Pointer): Integer;
begin
if Assigned(P1) then
begin
if Assigned(P2) then
begin
Result := VarCompare(PVariant(P1)^, PVariant(P2)^);
end
else
Result := 1;
end
else
begin
if Assigned(P2) then
Result := -1
else
Result := 0;
end;
end;
class function TcxVariantValueType.GetValue(PBuffer: PChar): Variant;
begin
Result := GetDataValue(@PBuffer);
end;
class procedure TcxVariantValueType.PrepareValueBuffer(var PBuffer: PChar);
begin
PBuffer := PPointer(PBuffer)^;
end;
class function TcxVariantValueType.Compare(P1, P2: Pointer): Integer;
begin
Result := CompareValues(PPointer(P1)^, PPointer(P2)^);
end;
class procedure TcxVariantValueType.FreeBuffer(PBuffer: PChar);
begin
Dispose(PVariant(PPointer(PBuffer)^));
end;
class function TcxVariantValueType.GetDataSize: Integer;
begin
Result := SizeOf(PVariant);
end;
class function TcxVariantValueType.GetDataValue(PBuffer: PChar): Variant;
begin
Result := PVariant(PPointer(PBuffer)^)^;
end;
class procedure TcxVariantValueType.SetDataValue(PBuffer: PChar; const Value: Variant);
var
P: PVariant;
begin
P := PPointer(PBuffer)^;
if P = nil then
begin
New(P);
PPointer(PBuffer)^ := P;
end;
P^ := Value;
end;
{ TcxObjectValueType }
class procedure TcxObjectValueType.FreeBuffer(PBuffer: PChar);
begin
TObject(PPointer(PBuffer)^).Free;
end;
class procedure TcxObjectValueType.ReadDataValue(PBuffer: PChar; AStream: TStream);
begin
// not supported
end;
class procedure TcxObjectValueType.SetDataValue(PBuffer: PChar; const Value: Variant);
begin
// TODO: if PInteger(PBuffer)^ <> 0 then FreeBuffer(PBuffer);
inherited SetDataValue(PBuffer, Value);
end;
class procedure TcxObjectValueType.WriteDataValue(PBuffer: PChar; AStream: TStream);
begin
// not supported
end;
{ TcxValueDef }
constructor TcxValueDef.Create(AValueDefs: TcxValueDefs; AValueTypeClass: TcxValueTypeClass);
begin
inherited Create;
FValueDefs := AValueDefs;
FValueTypeClass := AValueTypeClass;
FStored := True;
FTextStored := False;
FStreamStored := True;
end;
destructor TcxValueDef.Destroy;
begin
FValueDefs.Remove(Self);
inherited Destroy;
end;
procedure TcxValueDef.Assign(ASource: TcxValueDef);
begin
Stored := ASource.Stored;
TextStored := ASource.TextStored;
end;
function TcxValueDef.CompareValues(AIsNull1, AIsNull2: Boolean; P1, P2: PChar): Integer;
begin
if AIsNull1 then
begin
if AIsNull2 then
Result := 0
else
Result := -1
end
else
begin
if AIsNull2 then
Result := 1
else
Result := ValueTypeClass.CompareValues(P1, P2);
end;
end;
procedure TcxValueDef.Changed(AResyncNeeded: Boolean);
begin
if Assigned(ValueDefs) then
ValueDefs.Changed(Self, AResyncNeeded);
end;
function TcxValueDef.Compare(P1, P2: PChar): Integer;
begin
if IsNullValueEx(P1, Offset) then
begin
if IsNullValueEx(P2, Offset) then
Result := 0
else
Result := -1
end
else
begin
if IsNullValueEx(P2, Offset) then
Result := 1
else
Result := ValueTypeClass.Compare(IncPChar(P1, Offset + ValueFlagSize),
IncPChar(P2, Offset + ValueFlagSize));
end;
end;
procedure TcxValueDef.FreeBuffer(PBuffer: PChar);
var
PCurrent: PChar;
begin
if not Stored then Exit;
PCurrent := IncPChar(PBuffer, Offset);
if not IsNullValue(PCurrent) then
ValueTypeClass.FreeBuffer(IncPChar(PCurrent, ValueFlagSize));
if TextStored then
FreeTextBuffer(IncPChar(PCurrent, ValueFlagSize + DataSize));
end;
procedure TcxValueDef.FreeTextBuffer(PBuffer: PChar);
begin
TcxValueType.FreeTextBuffer(PBuffer);
end;
function TcxValueDef.GetDataValue(PBuffer: PChar): Variant;
begin
if IsNullValue(IncPChar(PBuffer, Offset)) then
Result := Null
else
Result := ValueTypeClass.GetDataValue(IncPChar(PBuffer, Offset + ValueFlagSize));
end;
function TcxValueDef.GetDisplayText(PBuffer: PChar): string;
begin
if TextStored then
Result := ValueTypeClass.GetDisplayText(
IncPChar(PBuffer, Offset + ValueFlagSize + DataSize))
else
begin
if IsNullValue(IncPChar(PBuffer, Offset)) then
Result := ''
else
Result := ValueTypeClass.GetDefaultDisplayText(
IncPChar(PBuffer, Offset + ValueFlagSize));
end;
end;
function TcxValueDef.GetLinkObject: TObject;
begin
Result := FLinkObject;
end;
function TcxValueDef.GetStored: Boolean;
begin
Result := FStored or not ValueDefs.DataStorage.StoredValuesOnly;
end;
procedure TcxValueDef.Init(var AOffset: Integer);
begin
FDataSize := ValueTypeClass.GetDataSize;
FOffset := AOffset;
if Stored then
begin
Inc(AOffset, ValueFlagSize);
Inc(AOffset, DataSize);
if TextStored then
Inc(AOffset, PointerSize);
FBufferSize := AOffset - FOffset;
end
else
FBufferSize := 0;
end;
function TcxValueDef.IsNullValue(PBuffer: PChar): Boolean;
begin
Result := PByte(PBuffer)^ = 0;
end;
function TcxValueDef.IsNullValueEx(PBuffer: PChar; AOffset: Integer): Boolean;
begin
Result := (PBuffer = nil) or IsNullValue(IncPChar(PBuffer, AOffset));
end;
procedure TcxValueDef.ReadDataValue(PBuffer: PChar; AStream: TStream);
function ReadNullFlag: Boolean;
begin
Result := ReadBooleanFunc(AStream);
end;
begin
if ReadNullFlag then
SetNull(IncPChar(PBuffer, Offset), True)
else
begin
SetNull(IncPChar(PBuffer, Offset), False);
ValueTypeClass.ReadDataValue(
IncPChar(PBuffer, Offset + ValueFlagSize), AStream);
end;
end;
procedure TcxValueDef.ReadDisplayText(PBuffer: PChar; AStream: TStream);
begin
if TextStored then
ValueTypeClass.ReadDisplayText(IncPChar(PBuffer, Offset + ValueFlagSize + DataSize), AStream);
end;
procedure TcxValueDef.SetDataValue(PBuffer: PChar; const Value: Variant);
begin
if VarIsNull(Value) then
SetNull(IncPChar(PBuffer, Offset), True)
else
begin
SetNull(IncPChar(PBuffer, Offset), False);
ValueTypeClass.SetDataValue(IncPChar(PBuffer, Offset + ValueFlagSize), Value);
end;
end;
procedure TcxValueDef.SetDisplayText(PBuffer: PChar; const DisplayText: string);
begin
if TextStored then
ValueTypeClass.SetDisplayText(
IncPChar(PBuffer, Offset + ValueFlagSize + DataSize), DisplayText);
end;
procedure TcxValueDef.SetLinkObject(Value: TObject);
begin
FLinkObject := Value;
end;
procedure TcxValueDef.SetNull(PBuffer: PChar; IsNull: Boolean);
begin
if IsNull then
begin
if not IsNullValue(PBuffer) then
begin
ValueTypeClass.FreeBuffer(IncPChar(PBuffer, ValueFlagSize));
FillChar((PBuffer + ValueFlagSize)^, DataSize, 0);
end;
PByte(PBuffer)^ := 0 // see also IsNullValue
end
else
PByte(PBuffer)^ := 1;
end;
procedure TcxValueDef.WriteDataValue(PBuffer: PChar; AStream: TStream);
procedure WriteNullFlag(ANull: Boolean);
begin
WriteBooleanProc(AStream, ANull);
end;
begin
if IsNullValue(IncPChar(PBuffer, Offset)) then
WriteNullFlag(True)
else
begin
WriteNullFlag(False);
ValueTypeClass.WriteDataValue(
IncPChar(PBuffer, Offset + ValueFlagSize), AStream);
end;
end;
procedure TcxValueDef.WriteDisplayText(PBuffer: PChar; AStream: TStream);
begin
if TextStored then
ValueTypeClass.WriteDisplayText(
IncPChar(PBuffer, Offset + ValueFlagSize + DataSize), AStream);
end;
function TcxValueDef.GetIsNeedConversion: Boolean;
begin
Result := ValueTypeClass.IsString;
end;
function TcxValueDef.GetTextStored: Boolean;
begin
if not Stored then
Result := False
else
Result := FTextStored;
end;
procedure TcxValueDef.SetStored(Value: Boolean);
begin
if FStored <> Value then
begin
FStored := Value;
Changed(False);
end;
end;
procedure TcxValueDef.SetTextStored(Value: Boolean);
begin
if FTextStored <> Value then
begin
FTextStored := Value;
Changed(True);
end;
end;
procedure TcxValueDef.SetValueTypeClass(Value: TcxValueTypeClass);
begin
if FValueTypeClass <> Value then
begin
FValueTypeClass := Value; // TODO: clear?
Changed(True);
end;
end;
{ TcxValueDefs }
constructor TcxValueDefs.Create(ADataStorage: TcxDataStorage);
begin
inherited Create;
FDataStorage := ADataStorage;
FItems := TList.Create;
DataStorage.InitStructure(Self);
end;
destructor TcxValueDefs.Destroy;
begin
Clear;
FItems.Free;
inherited Destroy;
end;
function TcxValueDefs.Add(AValueTypeClass: TcxValueTypeClass; AStored, ATextStored: Boolean; ALinkObject: TObject): TcxValueDef;
var
I: Integer;
begin
Result := GetValueDefClass.Create(Self, AValueTypeClass);
Result.LinkObject := ALinkObject;
Result.Stored := AStored;
Result.TextStored := ATextStored;
I := 0;
Result.Init(I);
DataStorage.InsertValueDef(FItems.Count, Result);
FItems.Add(Result);
DataStorage.InitStructure(Self);
end;
procedure TcxValueDefs.Clear;
begin
while FItems.Count > 0 do
TcxValueDef(FItems.Last).Free;
end;
procedure TcxValueDefs.Changed(AValueDef: TcxValueDef; AResyncNeeded: Boolean);
begin
DataStorage.ValueDefsChanged(AValueDef, AResyncNeeded);
end;
function TcxValueDefs.GetValueDefClass: TcxValueDefClass;
begin
Result := TcxValueDef;
end;
procedure TcxValueDefs.Prepare(AStartOffset: Integer);
var
I, AOffset: Integer;
begin
FRecordOffset := AStartOffset;
AOffset := FRecordOffset;
for I := 0 to Count - 1 do
Items[I].Init(AOffset);
FRecordSize := AOffset;
end;
procedure TcxValueDefs.Remove(AItem: TcxValueDef);
begin
DataStorage.RemoveValueDef(AItem);
FItems.Remove(AItem);
DataStorage.InitStructure(Self);
end;
function TcxValueDefs.GetStoredCount: Integer;
var
I: Integer;
begin
Result := 0;
for I := 0 to Count - 1 do
if Items[I].Stored then
Inc(Result);
end;
function TcxValueDefs.GetCount: Integer;
begin
Result := FItems.Count;
end;
function TcxValueDefs.GetItem(Index: Integer): TcxValueDef;
begin
if DataStorage.FValueDefsList <> nil then
Result := TcxValueDef(DataStorage.FValueDefsList[Index])
else
Result := TcxValueDef(FItems[Index]);
end;
{ TcxInternalValueDef }
function TcxInternalValueDef.GetLinkObject: TObject;
begin
if Assigned(FLinkObject) then
Result := TcxValueDef(FLinkObject).LinkObject
else
Result := nil;
end;
function TcxInternalValueDef.GetStored: Boolean;
begin
Result := True;
end;
function TcxInternalValueDef.GetValueDef: TcxValueDef;
begin
Result := TcxValueDef(FLinkObject);
end;
{ TcxInternalValueDefs }
function TcxInternalValueDefs.FindByLinkObject(ALinkObject: TObject): TcxValueDef;
var
I: Integer;
begin
Result := nil;
for I := Count - 1 downto 0 do
if Items[I].FLinkObject = ALinkObject then
begin
Result := Items[I] as TcxValueDef;
Break;
end;
end;
procedure TcxInternalValueDefs.RemoveByLinkObject(ALinkObject: TObject);
var
AItem: TcxValueDef;
begin
AItem := FindByLinkObject(ALinkObject);
if AItem <> nil then
AItem.Free;
end;
function TcxInternalValueDefs.GetValueDefClass: TcxValueDefClass;
begin
Result := TcxInternalValueDef;
end;
{ TcxValueDefReader }
constructor TcxValueDefReader.Create;
begin
inherited Create;
end;
function TcxValueDefReader.GetDisplayText(AValueDef: TcxValueDef): string;
begin
Result := '';
end;
function TcxValueDefReader.GetValue(AValueDef: TcxValueDef): Variant;
begin
Result := Null;
end;
function TcxValueDefReader.IsInternal(AValueDef: TcxValueDef): Boolean;
begin
Result := False;
end;
{ TcxDataStorage }
constructor TcxDataStorage.Create;
begin
inherited Create;
FRecordIDCounter := 1; // TODO: reset
FInternalValueDefs := TcxInternalValueDefs.Create(Self);
FValueDefs := TcxValueDefs.Create(Self);
FInternalRecordBuffers := TList.Create;
FRecordBuffers := TList.Create;
end;
destructor TcxDataStorage.Destroy;
begin
Clear(False);
FValueDefs.Free;
FInternalValueDefs.Free;
FRecordBuffers.Free;
FInternalRecordBuffers.Free;
inherited Destroy;
end;
function TcxDataStorage.AddInternalRecord: Integer;
var
I: Integer;
P: PChar;
begin
Result := 0;
for I := -1 downto -FInternalRecordBuffers.Count do
begin
if not IsRecordFlag(RecordBuffers[I], RecordFlag_Busy) then
begin
Result := I;
Break;
end;
end;
if Result = 0 then
Result := -FInternalRecordBuffers.Add(nil) - 1;
P := AllocRecordBuffer(Result);
ChangeRecordFlag(P, RecordFlag_Busy, True);
end;
function TcxDataStorage.AppendRecord: Integer;
begin
Result := FRecordBuffers.Add(nil);
CheckRecordID(Result);
end;
procedure TcxDataStorage.BeforeDestruction;
begin
FDestroying := True;
inherited BeforeDestruction;
end;
procedure TcxDataStorage.BeginLoad;
begin
CheckStructure;
end;
procedure TcxDataStorage.CheckStructure;
begin
(*
if FValueDefsChanged then
begin
InitStructure(ValueDefs);
// !
ClearInternalRecords;
InitStructure(InternalValueDefs);
// !
FValueDefsChanged := False;
end;
*)
end;
procedure TcxDataStorage.Clear(AWithoutInternal: Boolean);
begin
if not AWithoutInternal then
ClearInternalRecords;
ClearRecords(True);
end;
procedure TcxDataStorage.ClearInternalRecords;
var
I: Integer;
begin
for I := -FInternalRecordBuffers.Count to -1 do
FreeAndNilRecordBuffer(I);
FInternalRecordBuffers.Clear;
if Assigned(FOnClearInternalRecords) then
FOnClearInternalRecords(Self);
end;
procedure TcxDataStorage.ClearRecords(AClearList: Boolean);
var
I: Integer;
begin
for I := 0 to FRecordBuffers.Count - 1 do
FreeAndNilRecordBuffer(I);
if AClearList then
FRecordBuffers.Clear;
CheckRecordIDCounter;
CheckRecordID(-1); // all
end;
function TcxDataStorage.CompareRecords(ARecordIndex1, ARecordIndex2: Integer;
AValueDef: TcxValueDef): Integer;
var
P1, P2: PChar;
begin
P1 := RecordBuffers[ARecordIndex1];
P2 := RecordBuffers[ARecordIndex2];
Result := AValueDef.Compare(P1, P2);
end;
procedure TcxDataStorage.DeleteRecord(ARecordIndex: Integer);
begin
if ARecordIndex < 0 then
DeleteInternalRecord(ARecordIndex)
else
begin
FreeAndNilRecordBuffer(ARecordIndex);
FRecordBuffers.Delete(ARecordIndex);
CheckRecordIDCounter;
end;
end;
procedure TcxDataStorage.EndLoad;
begin
end;
function TcxDataStorage.GetDisplayText(ARecordIndex: Integer; AValueDef: TcxValueDef): string;
var
P: PChar;
begin
Result := '';
P := RecordBuffers[ARecordIndex];
if (P <> nil) and CheckValueDef(ARecordIndex, AValueDef) then
Result := AValueDef.GetDisplayText(P);
end;
function TcxDataStorage.GetCompareInfo(ARecordIndex: Integer; AValueDef: TcxValueDef;
var P: PChar): Boolean;
begin
P := RecordBuffers[ARecordIndex];
IncPChar(P, AValueDef.Offset);
Result := AValueDef.IsNullValue(P);
if not Result then
begin
IncPChar(P, ValueFlagSize);
AValueDef.ValueTypeClass.PrepareValueBuffer(P);
end;
end;
function TcxDataStorage.GetRecordID(ARecordIndex: Integer): Integer;
var
P: PChar;
begin
P := AllocRecordBuffer(ARecordIndex);
P := IncPChar(P, RecordFlagSize);
Result := PInteger(P)^;
end;
function TcxDataStorage.GetValue(ARecordIndex: Integer; AValueDef: TcxValueDef): Variant;
var
P: PChar;
begin
Result := Null;
P := RecordBuffers[ARecordIndex];
if (P <> nil) and CheckValueDef(ARecordIndex, AValueDef) then
Result := AValueDef.GetDataValue(P);
end;
procedure TcxDataStorage.InsertRecord(ARecordIndex: Integer);
begin
FRecordBuffers.Insert(ARecordIndex, nil);
CheckRecordID(ARecordIndex);
end;
procedure TcxDataStorage.ReadData(ARecordIndex: Integer; AStream: TStream);
function ReadNilFlag: Boolean;
begin
Result := ReadBooleanFunc(AStream);
end;
var
P: PChar;
I, AID: Integer;
AValueDef: TcxValueDef;
begin
if ReadNilFlag then
FreeAndNilRecordBuffer(ARecordIndex)
else
begin
P := AllocRecordBuffer(ARecordIndex);
if UseRecordID then
begin
AID := ReadIntegerFunc(AStream);
SetRecordID(ARecordIndex, AID);
CheckRecordIDCounterAfterLoad(AID);
end;
for I := 0 to ValueDefs.Count - 1 do
begin
AValueDef := ValueDefs[I];
if AValueDef.StreamStored then
begin
AValueDef.ReadDataValue(P, AStream);
if AValueDef.TextStored then
AValueDef.ReadDisplayText(P, AStream);
end;
end;
end;
end;
procedure TcxDataStorage.ReadRecord(ARecordIndex: Integer; AValueDefReader: TcxValueDefReader);
var
P: PChar;
I: Integer;
AValueDef: TcxValueDef;
AValueDefs: TcxValueDefs;
begin
P := AllocRecordBuffer(ARecordIndex);
AValueDefs := ValueDefsByRecordIndex(ARecordIndex);
for I := 0 to AValueDefs.Count - 1 do
begin
AValueDef := AValueDefs[I];
if not AValueDefReader.IsInternal(AValueDef) then
begin
AValueDef.SetDataValue(P, AValueDefReader.GetValue(AValueDef));
if AValueDef.TextStored then
AValueDef.SetDisplayText(P, AValueDefReader.GetDisplayText(AValueDef));
end;
end;
end;
procedure TcxDataStorage.ReadRecordFrom(AFromRecordIndex, AToRecordIndex: Integer;
AValueDefReader: TcxValueDefReader; ASetProc: TcxValueDefSetProc);
var
I: Integer;
AValueDefs: TcxValueDefs;
begin
AValueDefs := ValueDefsByRecordIndex(AFromRecordIndex);
for I := 0 to AValueDefs.Count - 1 do
ASetProc(AValueDefs[I], AFromRecordIndex, AToRecordIndex, AValueDefReader);
end;
procedure TcxDataStorage.SetDisplayText(ARecordIndex: Integer; AValueDef: TcxValueDef;
const Value: string);
var
P: PChar;
begin
P := AllocRecordBuffer(ARecordIndex);
if CheckValueDef(ARecordIndex, AValueDef) and AValueDef.TextStored then
AValueDef.SetDisplayText(P, Value);
end;
procedure TcxDataStorage.SetRecordID(ARecordIndex, AID: Integer);
var
P: PChar;
begin
P := AllocRecordBuffer(ARecordIndex);
P := IncPChar(P, RecordFlagSize);
PInteger(P)^ := AID;
end;
procedure TcxDataStorage.SetValue(ARecordIndex: Integer; AValueDef: TcxValueDef;
const Value: Variant);
var
P: PChar;
begin
P := AllocRecordBuffer(ARecordIndex);
if CheckValueDef(ARecordIndex, AValueDef) then
AValueDef.SetDataValue(P, Value);
end;
procedure TcxDataStorage.WriteData(ARecordIndex: Integer; AStream: TStream);
procedure WriteRecordInfo(PBuffer: PChar);
var
AID: Integer;
begin
WriteBooleanProc(AStream, PBuffer = nil);
if (PBuffer <> nil) and UseRecordID then
begin
AID := 0;
if PBuffer <> nil then
begin
PBuffer := IncPChar(PBuffer, RecordFlagSize);
AID := PInteger(PBuffer)^;
end;
WriteIntegerProc(AStream, AID);
end;
end;
var
P: PChar;
I: Integer;
AValueDef: TcxValueDef;
begin
P := PChar(FRecordBuffers[ARecordIndex]);
WriteRecordInfo(P);
if P <> nil then
for I := 0 to ValueDefs.Count - 1 do
begin
AValueDef := ValueDefs[I];
if AValueDef.StreamStored then
begin
AValueDef.WriteDataValue(P, AStream);
if AValueDef.TextStored then
AValueDef.WriteDisplayText(P, AStream);
end;
end;
end;
procedure TcxDataStorage.BeginStreaming(ACompare: TListSortCompare);
var
I: Integer;
AList: TList;
begin
AList := TList.Create;
for I := 0 to ValueDefs.Count - 1 do
AList.Add(ValueDefs[I]);
AList.Sort(ACompare);
FValueDefsList := AList;
end;
procedure TcxDataStorage.EndStreaming;
begin
FValueDefsList.Free;
FValueDefsList := nil;
end;
function TcxDataStorage.AllocRecordBuffer(Index: Integer): PChar;
var
AValueDefs: TcxValueDefs;
begin
Result := RecordBuffers[Index];
if Result = nil then
begin
AValueDefs := ValueDefsByRecordIndex(Index);
Result := AllocMem(AValueDefs.RecordSize);
RecordBuffers[Index] := Result;
end;
end;
function TcxDataStorage.CalcRecordOffset: Integer;
begin
Result := RecordFlagSize;
if UseRecordID then
Inc(Result, RecordIDSize);
end;
procedure TcxDataStorage.ChangeRecordFlag(PBuffer: PChar; AFlag: Byte; ATurnOn: Boolean);
begin
if PBuffer <> nil then
if ATurnOn then
PByte(PBuffer)^ := PByte(PBuffer)^ or AFlag
else
PByte(PBuffer)^ := PByte(PBuffer)^ and not AFlag;
end;
procedure TcxDataStorage.CheckRecordID(ARecordIndex: Integer);
procedure CheckID(AIndex: Integer);
begin
if GetRecordID(AIndex) = 0 then
begin
SetRecordID(AIndex, FRecordIDCounter);
Inc(FRecordIDCounter);
end;
end;
var
I: Integer;
begin
if not UseRecordID then Exit;
if ARecordIndex <> -1 then
CheckID(ARecordIndex)
else
for I := 0 to RecordCount - 1 do
CheckID(I);
end;
procedure TcxDataStorage.CheckRecordIDCounter;
begin
if FRecordBuffers.Count = 0 then FRecordIDCounter := 1; // TODO: reset
end;
procedure TcxDataStorage.CheckRecordIDCounterAfterLoad(ALoadedID: Integer);
begin
if FRecordIDCounter <= ALoadedID then
FRecordIDCounter := ALoadedID + 1;
end;
function TcxDataStorage.CheckValueDef(ARecordIndex: Integer; var AValueDef: TcxValueDef): Boolean;
begin
if not (AValueDef is TcxInternalValueDef) and
(ValueDefsByRecordIndex(ARecordIndex) = InternalValueDefs) then
AValueDef := InternalValueDefs.FindByLinkObject(AValueDef);
Result := AValueDef <> nil;
end;
procedure TcxDataStorage.DeleteInternalRecord(ARecordIndex: Integer);
//var
// P: PChar;
begin
if ARecordIndex >= 0 then Exit;
// P := RecordBuffers[ARecordIndex];
// ChangeRecordFlag(P, RecordFlag_Busy, False);
FreeAndNilRecordBuffer(ARecordIndex);
end;
procedure TcxDataStorage.FreeAndNilRecordBuffer(AIndex: Integer);
var
P: PChar;
I: Integer;
AValueDefs: TcxValueDefs;
begin
P := RecordBuffers[AIndex];
if P <> nil then
begin
AValueDefs := ValueDefsByRecordIndex(AIndex);
RecordBuffers[AIndex] := nil;
for I := 0 to AValueDefs.Count - 1 do
AValueDefs[I].FreeBuffer(P);
FreeMem(P);
end;
end;
procedure TcxDataStorage.InitStructure(AValueDefs: TcxValueDefs);
begin
AValueDefs.Prepare(CalcRecordOffset);
end;
procedure TcxDataStorage.InsertValueDef(AIndex: Integer; AValueDef: TcxValueDef);
var
I, AStartIndex, AEndIndex: Integer;
PBuffer, PSource, PDest: PChar;
AValueDefs: TcxValueDefs;
begin
AValueDefs := AValueDef.ValueDefs;
if AValueDefs = ValueDefs then
begin
InternalValueDefs.Add(AValueDef.ValueTypeClass, True, AValueDef.FTextStored, AValueDef);
AStartIndex := 0;
AEndIndex := FRecordBuffers.Count - 1;
end
else
begin
AStartIndex := -FInternalRecordBuffers.Count;
AEndIndex := -1;
end;
for I := AStartIndex to AEndIndex do
begin
PBuffer := RecordBuffers[I];
if PBuffer <> nil then
begin
ReallocMem(PBuffer, AValueDefs.RecordSize + AValueDef.BufferSize);
RecordBuffers[I] := PBuffer;
if AIndex < AValueDefs.Count then
begin
PSource := IncPChar(PBuffer, AValueDefs[AIndex].Offset);
PDest := IncPChar(PSource, AValueDef.BufferSize);
System.Move(PSource^, PDest^, AValueDefs.RecordSize - (PSource - PBuffer));
end
else
begin
PSource := PBuffer;
if AValueDefs.Count > 0 then
PSource := IncPChar(PSource, AValueDefs[AValueDefs.Count - 1].Offset +
AValueDefs[AValueDefs.Count - 1].BufferSize)
else
PSource := IncPChar(PSource, AValueDefs.RecordSize);
end;
FillChar(PSource^, AValueDef.BufferSize, 0);
end;
end;
end;
function TcxDataStorage.IsRecordFlag(PBuffer: PChar; AFlag: Byte): Boolean;
begin
Result := (PBuffer <> nil) and ((PByte(PBuffer)^ and AFlag) = AFlag);
end;
procedure TcxDataStorage.RemoveValueDef(AValueDef: TcxValueDef);
var
I, AStartIndex, AEndIndex: Integer;
PBuffer, PSource, PDest: PChar;
AValueDefs: TcxValueDefs;
AFreeAndNil: Boolean;
begin
AValueDefs := AValueDef.ValueDefs;
if AValueDefs = ValueDefs then
begin
InternalValueDefs.RemoveByLinkObject(AValueDef);
AStartIndex := 0;
AEndIndex := FRecordBuffers.Count - 1;
end
else
begin
AStartIndex := -FInternalRecordBuffers.Count;
AEndIndex := -1;
end;
AFreeAndNil := AValueDef.Stored and (AValueDefs.StoredCount <= 1);
for I := AStartIndex to AEndIndex do
begin
PBuffer := RecordBuffers[I];
if PBuffer <> nil then
if AFreeAndNil then
FreeAndNilRecordBuffer(I)
else
if AValueDef.Stored then
begin
AValueDef.FreeBuffer(PBuffer);
PDest := IncPChar(PBuffer, AValueDef.Offset);
PSource := IncPChar(PDest, AValueDef.BufferSize);
System.Move(PSource^, PDest^, AValueDefs.RecordSize - (PSource - PBuffer));
ReallocMem(PBuffer, AValueDefs.RecordSize - AValueDef.BufferSize); // existing data in the block is not affected!
RecordBuffers[I] := PBuffer;
end;
end;
end;
procedure TcxDataStorage.ValueDefsChanged(AValueDef: TcxValueDef; AResyncNeeded: Boolean);
//var
// AInternalValueDef: TcxValueDef;
begin
(*
if FDestroying then Exit;
if not FValueDefsChanged then
begin
ClearRecords(False);
FValueDefsChanged := True;
if AResyncNeeded and (AValueDef.ValueDefs = ValueDefs) then
begin
AInternalValueDef := InternalValueDefs.FindByLinkObject(AValueDef);
if AInternalValueDef <> nil then
AInternalValueDef.Assign(AValueDef);
end;
end;
*)
end;
function TcxDataStorage.ValueDefsByRecordIndex(Index: Integer): TcxValueDefs;
begin
if Index < 0 then
Result := FInternalValueDefs
else
Result := FValueDefs;
end;
function TcxDataStorage.GetRecordBuffer(Index: Integer): PChar;
begin
if Index >= 0 then
Result := PChar(FRecordBuffers[Index])
else
Result := PChar(FInternalRecordBuffers[-Index - 1]);
end;
function TcxDataStorage.GetRecordCount: Integer;
begin
Result := FRecordBuffers.Count;
end;
procedure TcxDataStorage.SetStoredValuesOnly(Value: Boolean);
begin
if FStoredValuesOnly <> Value then
begin
ClearRecords(False);
FStoredValuesOnly := Value;
InitStructure(ValueDefs);
end;
end;
procedure TcxDataStorage.SetRecordBuffer(Index: Integer; Value: PChar);
begin
if Index >= 0 then
FRecordBuffers[Index] := Value
else
FInternalRecordBuffers[-Index - 1] := Value;
end;
procedure TcxDataStorage.SetRecordCount(Value: Integer);
begin
if Value < 0 then Value := 0;
if RecordCount <> Value then
begin
// TODO: Capacity
while RecordCount < Value do
AppendRecord;
while RecordCount > Value do
DeleteRecord(RecordCount - 1);
end;
end;
procedure TcxDataStorage.SetUseRecordID(Value: Boolean);
begin
if FUseRecordID <> Value then
begin
ClearRecords(False);
FUseRecordID := Value;
InitStructure(ValueDefs);
end;
end;
{ TcxLookupList }
constructor TcxLookupList.Create;
begin
inherited Create;
FItems := TList.Create;
end;
destructor TcxLookupList.Destroy;
begin
Clear;
FItems.Free;
inherited Destroy;
end;
procedure TcxLookupList.Clear;
var
I: Integer;
begin
for I := 0 to FItems.Count - 1 do
Dispose(PcxLookupListItem(FItems[I]));
FItems.Clear;
end;
function TcxLookupList.Find(const AKeyValue: Variant; var AIndex: Integer): Boolean;
var
L, H, I, C: Integer;
begin
AIndex := 0;
Result := False;
L := 0;
H := FItems.Count - 1;
if L <= H then
repeat
I := (L + H) div 2;
C := VarCompare(PcxLookupListItem(FItems[I]).KeyValue, AKeyValue);
if C = 0 then
begin
AIndex := I;
Result := True;
Break;
end
else
if C < 0 then
L := I + 1
else
H := I - 1;
if L > H then
begin
AIndex := L;
Break;
end;
until False;
end;
procedure TcxLookupList.Insert(AIndex: Integer; const AKeyValue: Variant;
const ADisplayText: string);
var
P: PcxLookupListItem;
begin
New(P);
P.KeyValue := AKeyValue;
P.DisplayText := ADisplayText;
FItems.Insert(AIndex, P);
end;
function TcxLookupList.GetCount: Integer;
begin
Result := FItems.Count;
end;
function TcxLookupList.GetItem(Index: Integer): PcxLookupListItem;
begin
Result := PcxLookupListItem(FItems[Index]);
end;
{ TcxValueTypeClassList }
constructor TcxValueTypeClassList.Create;
begin
inherited Create;
FItems := TList.Create;
end;
destructor TcxValueTypeClassList.Destroy;
begin
FItems.Free;
inherited Destroy;
end;
function TcxValueTypeClassList.ItemByCaption(const ACaption: string): TcxValueTypeClass;
var
I: Integer;
begin
Result := nil;
for I := 0 to FItems.Count - 1 do
if TcxValueTypeClass(FItems[I]).Caption = ACaption then
begin
Result := TcxValueTypeClass(FItems[I]);
Break;
end;
end;
procedure TcxValueTypeClassList.RegisterItem(AValueTypeClass: TcxValueTypeClass);
begin
if FItems.IndexOf(TObject(AValueTypeClass)) = -1 then
FItems.Add(TObject(AValueTypeClass));
end;
procedure TcxValueTypeClassList.UnregisterItem(AValueTypeClass: TcxValueTypeClass);
begin
FItems.Remove(TObject(AValueTypeClass));
end;
function TcxValueTypeClassList.GetCount: Integer;
begin
Result := FItems.Count;
end;
function TcxValueTypeClassList.GetItem(Index: Integer): TcxValueTypeClass;
begin
Result := TcxValueTypeClass(FItems[Index]);
end;
initialization
cxValueTypeClassList.RegisterItem(TcxStringValueType);
cxValueTypeClassList.RegisterItem(TcxWideStringValueType);
cxValueTypeClassList.RegisterItem(TcxSmallintValueType);
cxValueTypeClassList.RegisterItem(TcxIntegerValueType);
cxValueTypeClassList.RegisterItem(TcxWordValueType);
cxValueTypeClassList.RegisterItem(TcxBooleanValueType);
cxValueTypeClassList.RegisterItem(TcxFloatValueType);
cxValueTypeClassList.RegisterItem(TcxCurrencyValueType);
cxValueTypeClassList.RegisterItem(TcxDateTimeValueType);
{$IFDEF DELPHI6}
cxValueTypeClassList.RegisterItem(TcxLargeIntValueType);
{$IFNDEF NONDB}
cxValueTypeClassList.RegisterItem(TcxFMTBcdValueType);
cxValueTypeClassList.RegisterItem(TcxSQLTimeStampValueType);
{$ENDIF}
{$ENDIF}
cxValueTypeClassList.RegisterItem(TcxVariantValueType);
cxValueTypeClassList.RegisterItem(TcxObjectValueType);
finalization
cxValueTypeClassList.UnregisterItem(TcxObjectValueType);
cxValueTypeClassList.UnregisterItem(TcxVariantValueType);
{$IFDEF DELPHI6}
{$IFNDEF NONDB}
cxValueTypeClassList.UnregisterItem(TcxSQLTimeStampValueType);
cxValueTypeClassList.UnregisterItem(TcxFMTBcdValueType);
{$ENDIF}
cxValueTypeClassList.UnregisterItem(TcxLargeIntValueType);
{$ENDIF}
cxValueTypeClassList.UnregisterItem(TcxDateTimeValueType);
cxValueTypeClassList.UnregisterItem(TcxCurrencyValueType);
cxValueTypeClassList.UnregisterItem(TcxFloatValueType);
cxValueTypeClassList.UnregisterItem(TcxBooleanValueType);
cxValueTypeClassList.UnregisterItem(TcxWordValueType);
cxValueTypeClassList.UnregisterItem(TcxIntegerValueType);
cxValueTypeClassList.UnregisterItem(TcxSmallintValueType);
cxValueTypeClassList.UnregisterItem(TcxWideStringValueType);
cxValueTypeClassList.UnregisterItem(TcxStringValueType);
FValueTypeClassList.Free;
FValueTypeClassList := nil;
end.