{************************************************************}
{                   Delphi VCL Extensions                    }
{                                                            }
{                   Extended data for entity                 }
{                                                            }
{      Copyright (c) 2002-2013 SoftGold software company     }
{                                                            }
{************************************************************}

unit ExtData;

{$DEFINE SORTDATA}

interface

uses Windows, Classes, SysUtils, sgConsts, sgFunction, MVFont, sgLists;

type
  TsgExtDataType = (edtUndefined, edtByte, edtInt16, edtInt, edtInt64,
    edtSingle, edtDouble, edtString, edtF2DPoint, edtF3DPoint, edtBinary,
    edtObject);

  PsgExtData = ^TsgExtData;
  TsgExtData = record
    EType: TsgExtdataType;
    ECode: SmallInt;
    EGroupCode: SmallInt;
    EData: Pointer;
  end;

  TsgCADExtendedData = class
  private
    FData: TsgList;
    FFlags: Byte;
    function GetData(const AIndex: Integer): TsgExtData;
    function GetDataBinary(const AIndex: Integer): PByte;
    function GetDataByte(const AIndex: Integer): Byte;
    function GetDataCode(const AIndex: Integer): Smallint;
    function GetDataCount: Integer;
    function GetDataDouble(const AIndex: Integer): Double;
    function GetDataInt(const AIndex: Integer): Integer;
    function GetDataInt16(const AIndex: Integer): SmallInt;
    function GetDataInt64(const AIndex: Integer): Int64;
    function GetDataObject(const AIndex: Integer): TObject;
    function GetDataPoint(const AIndex: Integer): TFPoint;
    function GetDataPoint2D(const AIndex: Integer): TF2DPoint;
    function GetDataSingle(const AIndex: Integer): Single;
    function GetDataString(const AIndex: Integer): string;
    function GetDataType(const AIndex: Integer): TsgExtdataType;
    function GetExtData(const AValue: Integer): PsgExtData;
    function GetGroupCode(const AIndex: Integer): Integer;
    procedure SetDataBinary(const AIndex: Integer; const AValue: PByte);
    procedure SetDataByte(const AIndex: Integer; const AValue: Byte);
    procedure SetDataDouble(const AIndex: Integer; const AValue: Double);
    procedure SetDataExtString(const AData: PsgExtData; const AValue: string);
    procedure SetDataInt(const AIndex, AValue: Integer);
    procedure SetDataInt16(const AIndex: Integer; const AValue: SmallInt);
    procedure SetDataInt64(const AIndex: Integer; const AValue: Int64);
    procedure SetDataObject(const AIndex: Integer; const AValue: TObject);
    procedure SetDataPoint(const AIndex: Integer; const AValue: TFPoint);
    procedure SetDataPoint2D(const AIndex: Integer; const AValue: TF2DPoint);
    procedure SetDataSingle(const AIndex: Integer; const AValue: Single);
    procedure SetDataString(const AIndex: Integer; const AValue: string);
    procedure SetGroupCode(const AIndex, AValue: Integer);
    procedure SetDataCode(const AIndex: Integer; const AValue: Smallint);
  protected
    function GetMemValue(const ANewType: TsgExtdataType;
      const ACount: Integer = 0): Pointer;
    function AddExtData(const ACode: Integer; const AType: TsgExtdataType;
      const AData: Pointer; const AGroupCode: Integer): Integer;
    procedure ClearData;
    function CompareExtDataByCode(const AVal1, AVal2: Pointer): Integer;
    procedure CreateData;
    procedure DisposeData(const AData: PsgExtData; const AEDataOnly: Boolean);
    function GetSorted: Boolean;
    function GetUseCode: Boolean; virtual;
    procedure SetSorted(const AValue: Boolean); virtual;
    procedure SetUseCode(const AValue: Boolean); virtual;
  public
    constructor Create; virtual;
    destructor Destroy; override;
    class function GetTypeByCode(const ACode: Integer): TsgExtDataType;
    function AddBinary(const ACode: SmallInt; const ACount: Byte;
      const AData: PByte; const AGroupCode: Integer = 1004): Integer;
    function AddByte(const ACode: SmallInt; const AData: Byte;
      const AGroupCode: Integer = Integer_1070): Integer;
    function AddDouble(const ACode: SmallInt; const AData: Double;
      const AGroupCode: Integer = Float_1040): Integer;
    function AddInt(const ACode: SmallInt; const AData: Integer;
      const AGroupCode: Integer = Integer_1071): Integer;
    function AddInt16(const ACode: SmallInt; const AData: Smallint;
      const AGroupCode: Integer = Integer_1070): Integer;
    function AddInt64(const ACode: SmallInt; const AData: Int64;
      const AGroupCode: Integer = String_1005): Integer;
    function AddListPoints(const ACodeCount, ACodePoint: Smallint;
      const AList: TList): Integer;
    function AddListPoints2D(const ACodeCount, ACodePoint: Smallint;
      const AList: TList): Integer;
    function AddObject(const ACode: SmallInt; const AData: TObject;
      const AGroupCode: Integer = String_1005): Integer;
    function AddPoint(const ACode: SmallInt; const AData: TFPoint;
      const AGroupCode: Integer = Float_1010): Integer;
    function AddPoint2D(const ACode: SmallInt; const AData: TF2DPoint;
      const AGroupCode: Integer = Float_1010): Integer;
    function AddSingle(const ACode: SmallInt; const AData: Single;
      const AGroupCode: Integer = Float_1040): Integer;
    function AddString(const ACode: SmallInt; const AData: string;
      const AGroupCode: Integer = String_1000): Integer;
    procedure AssignData(Source: TsgCADExtendedData); virtual;
    procedure ChangeType(const AIndex: Integer; const ANewType: TsgExtdataType);
    procedure Delete(const AIndex: Integer);
    function HasCode(const ACode: SmallInt; AIndex: PInteger = nil): Boolean;
    function IndexOfCode(const ACode: Integer): Integer;
    property Data[const AIndex: Integer]: TsgExtData read GetData;
    property DataByte[const AIndex: Integer]: Byte read GetDataByte
      write SetDataByte;
    property DataBinary[const AIndex: Integer]: PByte read GetDataBinary
      write SetDataBinary;
    property DataCode[const AIndex: Integer]: Smallint read GetDataCode
      write SetDataCode;
    property DataCount: Integer read GetDataCount;
    property DataDouble[const AIndex: Integer]: Double read GetDataDouble
      write SetDataDouble;
    property DataInt[const AIndex: Integer]: Integer read GetDataInt
      write SetDataInt;
    property DataInt16[const AIndex: Integer]: SmallInt read GetDataInt16
      write SetDataInt16;
    property DataInt64[const AIndex: Integer]: Int64 read GetDataInt64
      write SetDataInt64;
    property DataObject[const AIndex: Integer]: TObject read GetDataObject
      write SetDataObject;
    property DataPoint[const AIndex: Integer]: TFPoint read GetDataPoint
      write SetDataPoint;
    property DataPoint2D[const AIndex: Integer]: TF2DPoint read GetDataPoint2D
      write SetDataPoint2D;
    property DataSingle[const AIndex: Integer]: Single read GetDataSingle
      write SetDataSingle;
    property DataString[const AIndex: Integer]: String read GetDataString
      write SetDataString;
    property DataType[const AIndex: Integer]: TsgExtdataType read GetDataType;
    property GroupCode[const AIndex: Integer]: Integer read GetGroupCode
      write SetGroupCode;
    property Sorted: Boolean read GetSorted write SetSorted;
    property UseCode: Boolean read GetUseCode write SetUseCode;
  end;

  TsgBTIExtendedData = class(TsgCADExtendedData)
  private
    function GetxByteArray(const AIndex: Integer): Byte;
    function GetxDoubleArray(const AIndex: Integer): Double;
    function GetxIntArray(const AIndex: Integer): Integer;
    procedure SetxByteArray(const AIndex: Integer; const AValue: Byte);
    procedure SetxDoubleArray(const AIndex: Integer; const AValue: Double);
    procedure SetxIntArray(const AIndex, AValue: Integer);
    function GetxByteCount: Integer;
    function GetxDoubleCount: Integer;
    function GetxIntCount: Integer;
  protected
    function GetUseCode: Boolean; override;
    procedure SetSorted(const AValue: Boolean); override;
  public
    constructor Create; override;
    property xByteArray[const AIndex: Integer]: Byte read GetxByteArray
      write SetxByteArray;
    property xDoubleArray[const AIndex: Integer]: Double read GetxDoubleArray
      write SetxDoubleArray;
    property xIntArray[const AIndex: Integer]: Integer read GetxIntArray
      write SetxIntArray;
    property xByteCount: Integer read GetxByteCount;
    property xDoubleCount: Integer read GetxDoubleCount;
    property xIntCount: Integer read GetxIntCount;
  end;

implementation

const
  cnstExdTadaClear: TsgExtData = (EType: edtUndefined; ECode: 0; EGroupCode: 0;
    EData: nil);

{ TsgExtendedData }

function TsgCADExtendedData.GetData(const AIndex: Integer): TsgExtData;
var
  vData: PsgExtData;
begin
  vData := GetExtData(AIndex);
  if vData <> nil then
    Result := vData^
  else
    Result := cnstExdTadaClear;
end;

function TsgCADExtendedData.GetDataBinary(const AIndex: Integer): PByte;
var
  vData: PsgExtData;
begin
  Result := nil;
  vData := GetExtData(AIndex);
  if vData <> nil then
    Result := vData^.EData;
end;

function TsgCADExtendedData.GetDataByte(const AIndex: Integer): Byte;
var
  vData: PsgExtData;
begin
  Result := 0;
  vData := GetExtData(AIndex);
  if vData <> nil then
    Result := PByte(vData^.EData)^;
end;

function TsgCADExtendedData.GetDataCode(const AIndex: Integer): Smallint;
begin
  Result := -1;
  if FData <> nil then
    Result := PsgExtData(FData[AIndex])^.ECode;
end;

function TsgCADExtendedData.GetDataCount: Integer;
begin
  if FData <> nil then
    Result := FData.Count
  else
    Result := 0;
end;

function TsgCADExtendedData.GetDataDouble(const AIndex: Integer): Double;
var
  vData: PsgExtData;
begin
  Result := 0;
  vData := GetExtData(AIndex);
  if vData <> nil then
    Result := PDouble(vData^.EData)^;
end;

function TsgCADExtendedData.GetDataInt(const AIndex: Integer): Integer;
var
  vData: PsgExtData;
begin
  Result := 0;
  vData := GetExtData(AIndex);
  if vData <> nil then
    Result := PInteger(vData^.EData)^;
end;

function TsgCADExtendedData.GetDataInt16(const AIndex: Integer): SmallInt;
var
  vData: PsgExtData;
begin
  Result := 0;
  vData := GetExtData(AIndex);
  if vData <> nil then
    Result := PSmallInt(vData^.EData)^;
end;

function TsgCADExtendedData.GetDataInt64(const AIndex: Integer): Int64;
var
  vData: PsgExtData;
begin
  Result := 0;
  vData := GetExtData(AIndex);
  if vData <> nil then
    Result := PInt64(vData^.EData)^;
end;

function TsgCADExtendedData.GetDataObject(const AIndex: Integer): TObject;
var
  vData: PsgExtData;
begin
  Result := nil;
  vData := GetExtData(AIndex);
  if vData <> nil then
    Result := PPointer(vData^.EData)^;
end;

function TsgCADExtendedData.GetDataPoint(const AIndex: Integer): TFPoint;
var
  vData: PsgExtData;
begin
  vData := GetExtData(AIndex);
  if vData <> nil then
    Result := PFPoint(vData^.EData)^
  else
    Result := cnstFPointZero;
end;

function TsgCADExtendedData.GetDataPoint2D(const AIndex: Integer): TF2DPoint;
var
  vData: PsgExtData;
begin
  vData := GetExtData(AIndex);
  if vData <> nil then
    Result := PF2DPoint(vData^.EData)^
  else
    Result := cnstF2DPointZero;
end;

function TsgCADExtendedData.GetDataSingle(const AIndex: Integer): Single;
var
  vData: PsgExtData;
begin
  Result := 0;
  vData := GetExtData(AIndex);
  if vData <> nil then
    Result := PSingle(vData^.EData)^;
end;

function TsgCADExtendedData.GetDataString(const AIndex: Integer): string;
var
  vSize: Integer;
  vBytes: PByte;
  vData: PsgExtData;
begin
  Result := '';
  vData := GetExtData(AIndex);
  if vData <> nil then
  begin
    vBytes := vData^.EData;
    if vBytes <> nil then
    begin
      vSize := PInteger(vBytes)^;
      Inc(vBytes, SizeOf(Integer));
      SetString(Result, PChar(vBytes), vSize div SizeOf(Char));
    end;
  end;
end;

function TsgCADExtendedData.GetDataType(const AIndex: Integer): TsgExtdataType;
var
  vData: PsgExtData;
begin
  Result := edtUndefined;
  vData := GetExtData(AIndex);
  if vData <> nil then
    Result := vData^.EType;
end;

function TsgCADExtendedData.GetExtData(const AValue: Integer): PsgExtData;
var
  vIndex: Integer;
begin
  Result := nil;
  if FData <> nil then
  begin
    if UseCode then
    begin
      vIndex := IndexOfCode(AValue);
      if vIndex > -1 then
        Result := FData[vIndex];
    end
    else
      Result := FData[AValue];
  end;
end;

function TsgCADExtendedData.GetGroupCode(const AIndex: Integer): Integer;
var
  vData: PsgExtData;
begin
  Result := 0;
  vData := GetExtData(AIndex);
  if vData <> nil then
    Result := vData^.EGroupCode
end;

function TsgCADExtendedData.GetMemValue(const ANewType: TsgExtdataType;
  const ACount: Integer = 0): Pointer;
var
  vPByte: PByte absolute Result;
  vPInt: PInteger absolute Result;
  vPInt16: PSmallInt absolute Result;
  vPInt64: PInt64 absolute Result;
  vPSingle: PSingle absolute Result;
  vPDouble: PDouble absolute Result;
  vPF2DPoint: PF2DPoint absolute Result;
  vPF3DPoint: PFPoint absolute Result;
begin
  Result := nil;
  case ANewType of
    edtByte:     New(vPByte);
    edtInt16:    New(vPInt16);
    edtInt:      New(vPInt);
    edtint64:    New(vPInt64);
    edtSingle:   New(vPSingle);
    edtDouble:   New(vPDouble);
    edtF2DPoint: New(vPF2DPoint);
    edtF3DPoint: New(vPF3DPoint);
    edtBinary, edtString:
      begin
        if ACount > 0 then
        begin
          Result := AllocMem(ACount + SizeOf(Byte));
          PByte(Result)^ := ACount;
        end;
      end;
  end;
end;

procedure TsgCADExtendedData.SetDataBinary(const AIndex: Integer;
  const AValue: PByte);
var
  vExtData: PsgExtData;
begin
  vExtData := GetExtData(AIndex);
  if vExtData <> nil then
  begin
    if vExtData^.EData <> nil then
    begin
      ReallocMem(PByte(vExtData^.EData), 0);
      vExtData^.EData := nil;
    end;
    vExtData^.EData := AllocMem(AValue^ + SizeOf(Byte));
    CopyMemory(vExtData^.EData, AValue, AValue^ + SizeOf(Byte));
  end;
end;

procedure TsgCADExtendedData.SetDataByte(const AIndex: Integer;
  const AValue: Byte);
var
  vData: PsgExtData;
begin
  vData := GetExtData(AIndex);
  if vData <> nil then
    PByte(vData^.EData)^ := AValue;
end;

procedure TsgCADExtendedData.SetDataCode(const AIndex: Integer;
  const AValue: Smallint);
var
  vData: PsgExtData;
begin
  vData := GetExtData(AIndex);
  if vData <> nil then
    vData^.ECode := AValue;
end;

procedure TsgCADExtendedData.SetDataDouble(const AIndex: Integer;
  const AValue: Double);
var
  vData: PsgExtData;
begin
  vData := GetExtData(AIndex);
  if vData <> nil then
    PDouble(vData^.EData)^ := AValue;
end;

procedure TsgCADExtendedData.SetDataExtString(const AData: PsgExtData;
  const AValue: string);
var
  vBytes: PByte;
  vSize: Integer;
  S: string;
begin
  if AData^.EData <> nil then
  begin
    ReallocMem(PByte(AData.EData), 0);
    AData.EData := nil;
  end;
  S := AValue;
  if Length(S) > cnstMaxStringLen then
    SetLength(S, cnstMaxStringLen);
  if Length(S) > 0 then
  begin
    vSize := Length(S) * SizeOf(Char);
    vBytes := AllocMem(vSize + SizeOf(Integer));
    AData.EData := vBytes;
    PInteger(vBytes)^ := vSize;
    Inc(vBytes, SizeOf(Integer));
    Move(S[1], vBytes^, vSize);
  end;
end;

procedure TsgCADExtendedData.SetDataInt(const AIndex, AValue: Integer);
var
  vData: PsgExtData;
begin
  vData := GetExtData(AIndex);
  if vData <> nil then
    PInteger(vData^.EData)^ := AValue;
end;

procedure TsgCADExtendedData.SetDataInt16(const AIndex: Integer;
  const AValue: SmallInt);
var
  vData: PsgExtData;
begin
  vData := GetExtData(AIndex);
  if vData <> nil then
    PSmallInt(vData^.EData)^ := AValue;
end;

procedure TsgCADExtendedData.SetDataInt64(const AIndex: Integer;
  const AValue: Int64);
var
  vData: PsgExtData;
begin
  vData := GetExtData(AIndex);
  if vData <> nil then
    PInt64(vData^.EData)^ := AValue;
end;

procedure TsgCADExtendedData.SetDataObject(const AIndex: Integer;
  const AValue: TObject);
var
  vData: PsgExtData;
begin
  vData := GetExtData(AIndex);
  if vData <> nil then
    PPointer(vData^.EData)^ := AValue
end;

procedure TsgCADExtendedData.SetDataPoint(const AIndex: Integer;
  const AValue: TFPoint);
var
  vData: PsgExtData;
begin
  vData := GetExtData(AIndex);
  if vData <> nil then
    PFPoint(vData^.EData)^ := AValue;
end;

procedure TsgCADExtendedData.SetDataPoint2D(const AIndex: Integer;
  const AValue: TF2DPoint);
var
  vData: PsgExtData;
begin
  vData := GetExtData(AIndex);
  if vData <> nil then
    PF2DPoint(vData^.EData)^ := AValue;
end;

procedure TsgCADExtendedData.SetDataSingle(const AIndex: Integer;
  const AValue: Single);
var
  vData: PsgExtData;
begin
  vData := GetExtData(AIndex);
  if vData <> nil then
    PSingle(vData^.EData)^ := AValue;
end;

procedure TsgCADExtendedData.SetDataString(const AIndex: Integer;
  const AValue: string);
var
  vData: PsgExtData;
begin
  vData := GetExtData(AIndex);
  if vData <> nil then
    SetDataExtString(vData, AValue);
end;

procedure TsgCADExtendedData.SetGroupCode(const AIndex, AValue: Integer);
var
  vData: PsgExtData;
begin
  vData := GetExtData(AIndex);
  if vData <> nil then
    vData^.EGroupCode := AValue;
end;

function TsgCADExtendedData.AddExtData(const ACode: Integer;
  const AType: TsgExtdataType; const AData: Pointer;
  const AGroupCode: Integer): Integer;
var
  vData: PsgExtData;
begin
  if FData = nil then
    CreateData;
  New(vData);
  vData^.ECode := ACode;
  vData^.EType := AType;
  vData^.EGroupCode := AGroupCode;
  vData^.EData := AData;
  Result := FData.Add(vData);
end;

procedure TsgCADExtendedData.ChangeType(const AIndex: Integer;
  const ANewType: TsgExtdataType);
var
  vItem: PsgExtData;
begin
  vItem := FData.Items[AIndex];
  if (vItem <> nil) and (vItem^.EType <> ANewType) then
  begin
    DisposeData(vItem, True);
    vItem^.EType := ANewType;
    vItem^.EData := GetMemValue(ANewType);
  end;
end;

procedure TsgCADExtendedData.ClearData;
var
  I: Integer;
begin
  if FData <> nil then
  begin
    for I := 0 to FData.Count - 1 do
      DisposeData(FData[I], False);
    FData.Free;
    FData := nil;
  end;
end;

function TsgCADExtendedData.CompareExtDataByCode(
  const AVal1, AVal2: Pointer): Integer;
begin
  Result := PsgExtData(AVal1)^.ECode - PsgExtData(AVal2)^.ECode;
end;

procedure TsgCADExtendedData.CreateData;
begin
  FData := TsgList.Create;
  FData.Duplicates := dupAccept;
  FData.ProcCompare := CompareExtDataByCode;
  FData.Sorted := Sorted;
end;

procedure TsgCADExtendedData.DisposeData(const AData: PsgExtData;
  const AEDataOnly: Boolean);
var
  vBytes: PByte;
begin
  case AData^.EType of
    edtByte:      Dispose(PByte(AData^.EData));
    edtInt:       Dispose(PInteger(AData^.EData));
    edtInt16:     Dispose(PSmallInt(AData^.EData));
    edtint64:     Dispose(PInt64(AData^.EData));
    edtSingle:    Dispose(PSingle(AData^.EData));
    edtDouble:    Dispose(PDouble(AData^.EData));
    edtF2DPoint:  Dispose(PF2DPoint(AData^.EData));
    edtF3DPoint:  Dispose(PFPoint(AData^.EData));
    edtString,
    edtBinary:
      begin
        vBytes := AData.EData;
        ReallocMem(vBytes, 0);
      end;
    edtObject:    Dispose(PPointer(AData^.EData));
  end;
  if AEDataOnly then
    AData.EData := nil
  else
    Dispose(AData);
end;

function TsgCADExtendedData.GetSorted: Boolean;
begin
  Result := (FFlags and 2) <> 0;
end;

class function TsgCADExtendedData.GetTypeByCode(
  const ACode: Integer): TsgExtDataType;
begin
  Result := edtUndefined;
  case ACode of
    0..4,6..9, 300..309, 410..419, 999, 1000..1009:
      Result := edtString;//String
    10..37:
      Result := edtF3DPoint;//Double precision 3D point
    38..59, 110..139, 210..239, 1010..1059:
      Result := edtDouble;//Double precision floating point value
    60..79, 170..179, 270..289, 370..389, 400..409, 1060..1070:
      Result := edtInt16;//6-bit integer value
    90..99, 1071:
      Result := edtInt;//32-bit integer value
    100..104, 106..109:
      Result := edtString;//255-character maximum; less for Unicode strings
    5, 105, 310..369, 390..399:
      Result := edtInt64;//String representing hexadecimal (hex) handle value
    140..149:
      Result := edtDouble;//Double precision scalar floating-point value
    290..299:
      Result := edtByte;//Boolean flag value
  end;
end;

function TsgCADExtendedData.GetUseCode: Boolean;
begin
  Result := (FFlags and 1) <> 0;
end;

procedure TsgCADExtendedData.SetSorted(const AValue: Boolean);
begin
  FFlags := (FFlags and 253) or Byte(AValue);
  if FData <> nil then
    FData.Sorted := Sorted;
end;

procedure TsgCADExtendedData.SetUseCode(const AValue: Boolean);
begin
  FFlags := (FFlags and 254) or Byte(AValue);
end;

constructor TsgCADExtendedData.Create;
begin
end;

destructor TsgCADExtendedData.Destroy;
begin
  ClearData;
  inherited Destroy;
end;

function TsgCADExtendedData.AddBinary(const ACode: SmallInt;
  const ACount: Byte; const AData: PByte; const AGroupCode: Integer): Integer;
var
  vExtData: PsgExtData;
  vBytes: PByte;
begin
  Result := AddExtData(ACode, edtBinary, nil, AGroupCode);
  vExtData := FData[Result];
  vExtData^.EData := AllocMem(ACount + SizeOf(Byte));
  vBytes := vExtData^.EData;
  vBytes^ := ACount;
  Inc(vBytes, SizeOf(Byte));
  if AData <> nil then
    CopyMemory(vBytes, AData, ACount);
end;

function TsgCADExtendedData.AddByte(const ACode: SmallInt;
  const AData: Byte; const AGroupCode: Integer): Integer;
var
  vData: PByte;
begin
  New(vData);
  vData^ := AData;
  Result := AddExtData(ACode, edtByte, vData, AGroupCode);
end;

function TsgCADExtendedData.AddDouble(const ACode: SmallInt;
  const AData: Double; const AGroupCode: Integer): Integer;
var
  vData: PDouble;
begin
  New(vData);
  vData^ := AData;
  Result := AddExtData(ACode, edtDouble, vData, AGroupCode);
end;

function TsgCADExtendedData.AddInt(const ACode: SmallInt;
  const AData: Integer; const AGroupCode: Integer): Integer;
var
  vData: PInteger;
begin
  New(vData);
  vData^ := AData;
  Result := AddExtData(ACode, edtInt, vData, AGroupCode);
end;

function TsgCADExtendedData.AddInt16(const ACode, AData: Smallint;
  const AGroupCode: Integer): Integer;
var
  vData: PSmallInt;
begin
  New(vData);
  vData^ := AData;
  Result := AddExtData(ACode, edtint16, vData, AGroupCode);
end;

function TsgCADExtendedData.AddInt64(const ACode: SmallInt;
  const AData: Int64; const AGroupCode: Integer): Integer;
var
  vData: PInt64;
begin
  New(vData);
  vData^ := AData;
  Result := AddExtData(ACode, edtint64, vData, AGroupCode);
end;

function TsgCADExtendedData.AddListPoints(const ACodeCount,
  ACodePoint: Smallint; const AList: TList): Integer;
var
  I: Integer;
begin
  Result := -1;
  if (AList <> nil) and (AList.Count > 0) then
  begin
    Result := AddInt(ACodeCount, AList.Count);
    for I := 0 to AList.Count - 1 do
      AddPoint(ACodePoint, PFPoint(AList.List[I])^);
  end;
end;

function TsgCADExtendedData.AddListPoints2D(const ACodeCount,
  ACodePoint: Smallint; const AList: TList): Integer;
var
  I: Integer;
begin
  Result := -1;
  if (AList <> nil) and (AList.Count > 0) then
  begin
    Result := AddInt(ACodeCount, AList.Count);
    for I := 0 to AList.Count - 1 do
      AddPoint2D(ACodePoint, PF2DPoint(AList.List[I])^);
  end;
end;

function TsgCADExtendedData.AddObject(const ACode: SmallInt;
  const AData: TObject; const AGroupCode: Integer): Integer;
var
  vData: PPointer;
begin
  New(vData);
  vData^ := AData;
  Result := AddExtData(ACode, edtObject, vData, AGroupCode);
end;

function TsgCADExtendedData.AddPoint(const ACode: SmallInt;
  const AData: TFPoint; const AGroupCode: Integer): Integer;
var
  vData: PFPoint;
begin
  New(vData);
  vData^ := AData;
  Result := AddExtData(ACode, edtF3DPoint, vData, AGroupCode);
end;

function TsgCADExtendedData.AddPoint2D(const ACode: SmallInt;
  const AData: TF2DPoint; const AGroupCode: Integer): Integer;
var
  vData: PF2DPoint;
begin
  New(vData);
  vData^ := AData;
  Result := AddExtData(ACode, edtF2DPoint, vData, AGroupCode);
end;

function TsgCADExtendedData.AddSingle(const ACode: SmallInt;
  const AData: Single; const AGroupCode: Integer): Integer;
var
  vData: PSingle;
begin
  New(vData);
  vData^ := AData;
  Result := AddExtData(ACode, edtSingle, vData, AGroupCode);
end;

function TsgCADExtendedData.AddString(const ACode: SmallInt;
  const AData: string; const AGroupCode: Integer): Integer;
begin
  Result := AddExtData(ACode, edtString, nil, AGroupCode);
  SetDataExtString(FData[Result], AData);
end;

procedure TsgCADExtendedData.AssignData(Source: TsgCADExtendedData);
var
  I: Integer;
  vPBytes: PByte;
begin
  ClearData;
  FFlags := Source.FFlags;
  for I := 0 to Source.DataCount - 1 do
  begin
    case Source.DataType[I] of
      edtByte:     Self.AddByte(Source.DataCode[I], Source.DataByte[I], Source.GroupCode[I]);
      edtInt:      Self.AddInt(Source.DataCode[I], Source.DataInt[I], Source.GroupCode[I]);
      edtInt16:    Self.AddInt16(Source.DataCode[I], Source.DataInt16[I], Source.GroupCode[I]);
      edtint64:    Self.AddInt64(Source.DataCode[I], Source.DataInt64[I], Source.GroupCode[I]);
      edtSingle:   Self.AddSingle(Source.DataCode[I], Source.DataSingle[I], Source.GroupCode[I]);
      edtDouble:   Self.AddDouble(Source.DataCode[I], Source.DataDouble[I], Source.GroupCode[I]);
      edtF2DPoint: Self.AddPoint2D(Source.DataCode[I], Source.DataPoint2D[I], Source.GroupCode[I]);
      edtF3DPoint: Self.AddPoint(Source.DataCode[I], Source.DataPoint[I], Source.GroupCode[I]);
      edtString:   Self.AddString(Source.DataCode[I], Source.DataString[I], Source.GroupCode[I]);
      edtBinary:
        begin
          vPBytes := Source.DataBinary[I];
          AddBinary(Source.DataCode[I], vPBytes^, vPBytes);
        end;
      edtObject:  Self.AddObject(Source.DataCode[I], Source.DataObject[I], Source.GroupCode[I]);
    end;
  end;
end;

procedure TsgCADExtendedData.Delete(const AIndex: Integer);
var
  vIndex: Integer;
begin
  if FData <> nil then
  begin
    if UseCode then
      vIndex := IndexOfCode(AIndex)
    else
      vIndex := AIndex;
    if vIndex > -1 then
    begin
      DisposeData(FData[vIndex], False);
      FData.Delete(vIndex);
      if FData.Count = 0 then
      begin
        FData.Free;
        FData := nil;
      end;
    end;
  end;
end;

function TsgCADExtendedData.HasCode(const ACode: SmallInt;
  AIndex: PInteger = nil): Boolean;
var
  vData: TsgExtData;
  vIndex: Integer;
begin
  Result := False;
  if FData <> nil then
  begin
    vData.ECode := ACode;
    vIndex := FData.IndexOf(@vData);
    Result := vIndex > -1;
    if Result and (AIndex <> nil) then
      AIndex^ := vIndex;
  end;
end;

function TsgCADExtendedData.IndexOfCode(const ACode: Integer): Integer;
var
  vData: TsgExtData;
begin
  if FData <> nil then
  begin
    vData.ECode := ACode;
    Result := FData.IndexOf(@vData);
  end
  else
    Result := -1;
end;

{ TsgBTIExtendedData }

function TsgBTIExtendedData.GetxByteArray(const AIndex: Integer): Byte;
var
  vFlags: Byte;
begin
  vFlags := FFlags;
  UseCode := False;
  Result := DataByte[AIndex];
  FFlags := vFlags;
end;

function TsgBTIExtendedData.GetxByteCount: Integer;
begin
  Result := 6;
end;

function TsgBTIExtendedData.GetxDoubleArray(const AIndex: Integer): Double;
var
  vFlags: Byte;
begin
  vFlags := FFlags;
  UseCode := False;
  Result := DataDouble[AIndex + 8];
  FFlags := vFlags;
end;

function TsgBTIExtendedData.GetxDoubleCount: Integer;
begin
  Result := 11;
end;

function TsgBTIExtendedData.GetxIntArray(const AIndex: Integer): Integer;
var
  vFlags: Byte;
begin
  vFlags := FFlags;
  UseCode := False;
  Result := DataInt[AIndex + 6];
  FFlags := vFlags;
end;

function TsgBTIExtendedData.GetxIntCount: Integer;
begin
  Result := 2;
end;

procedure TsgBTIExtendedData.SetxByteArray(const AIndex: Integer;
  const AValue: Byte);
var
  vFlags: Byte;
begin
  vFlags := FFlags;
  UseCode := False;
  DataByte[AIndex] := AValue;
  FFlags := vFlags;
end;

procedure TsgBTIExtendedData.SetxDoubleArray(const AIndex: Integer;
  const AValue: Double);
var
  vFlags: Byte;
begin
  vFlags := FFlags;
  UseCode := False;
  DataDouble[AIndex + 8] := AValue;
  FFlags := vFlags;
end;

procedure TsgBTIExtendedData.SetxIntArray(const AIndex, AValue: Integer);
var
  vFlags: Byte;
begin
  vFlags := FFlags;
  UseCode := False;
  DataInt[AIndex + 6] := AValue;
  FFlags := vFlags;
end;

function TsgBTIExtendedData.GetUseCode: Boolean;
begin
  Result := False;
end;

procedure TsgBTIExtendedData.SetSorted(const AValue: Boolean);
begin
end;

constructor TsgBTIExtendedData.Create;
var
  I: Integer;
begin
  inherited Create;
  inherited SetSorted(False);

  AddByte(280, 0);
  AddByte(281, 0);
  AddByte(284, 0);
  AddByte(285, 0);
  AddByte(286, 0);
  AddByte(287, 0);

  AddInt(90, 0);
  AddInt(91, 0);

  for I := 1 to xDoubleCount do
   AddDouble(1040, 0);
end;

end.
