base_conv.pas

来自「Delphi脚本控件」· PAS 代码 · 共 383 行

PAS
383
字号
////////////////////////////////////////////////////////////////////////////
// PAXScript Interpreter
// Author: Alexander Baranovsky (ab@cable.netlux.org)
// ========================================================================
// Copyright (c) Alexander Baranovsky, 2003-2005. All rights reserved.
// Code Version: 3.0
// ========================================================================
// Unit: BASE_CONV.pas
// ========================================================================
////////////////////////////////////////////////////////////////////////////

{$I PaxScript.def}
unit BASE_CONV;
interface

uses
{$IFDEF VARIANTS}
  Variants,
{$ENDIF}
  SysUtils,
  BASE_CONSTS,
  BASE_SYS;

function GetVariantValue(Scripter, Address: Pointer; TypeID: Integer;
                         const TypeName: String = ''): Variant;
procedure PutVariantValue(Scripter, Address: Pointer; const AValue: Variant; typeID: Integer);
function DynamicArrayToVariant(Scripter, P: Pointer; const ArrayTypeName: string; ElTypeID: Integer): Variant;
function VariantToDynamicArray(Scripter: Pointer; const V: Variant; ElTypeID: Integer): Pointer;
procedure EraseDynamicArray(Scripter, P: Pointer; ElTypeID: Integer);
function ToCurrency(const V: Variant): Currency;

implementation

uses
  BASE_CLASS, BASE_EXTERN, BASE_SCRIPTER;

function GetVariantValue(Scripter, Address: Pointer; TypeID: Integer;
                         const TypeName: String = ''): Variant;
var
  Instance: TObject;
  SO: TPaxScriptObject;
  S: TByteSet;
  ClassRec: TPaxClassRec;
  Dbl: Double;
begin
  case TypeID of
    typeVARIANT: result := Variant(Address^);
    typeENUM:
      result := Byte(Address^);
    typeOLEVARIANT: result := Variant(Address^);
    typeBYTE: result := Integer(Byte(Address^));
    typeCHAR: result := Char(Address^);
    typeBOOLEAN: result := Boolean(Address^);
    typeWORDBOOL: result := WordBool(Address^);
    typeLONGBOOL: result := LongBool(Address^);
    typeINTEGER: result := Integer(Address^);
    typeCARDINAL: result := Integer(Cardinal(Address^));
    typePOINTER: result := Integer(Address^);
    typeDOUBLE: result := Double(Address^);
    typeSTRING: result := String(Address^);
    typePCHAR: result := String(Address^);
    typeWORD: result := Integer(Word(Address^));
    typeSHORTINT: result := Integer(ShortInt(Address^));
    typeSMALLINT: result := Integer(SmallInt(Address^));
    typeINT64: result := Integer(Int64(Address^));
    typeSINGLE:  begin Dbl := Single(Address^); result := Dbl; end;
    typeCURRENCY: result := Double(Currency(Address^));
    typeCOMP: result := Double(Comp(Address^));
//  typeREAL48: result := Real48(Address^);
    typeEXTENDED: begin Dbl := Extended(Address^); result := Dbl; end;
    typeSHORTSTRING: result := ShortString(Address^);
    typeWIDECHAR: result := WideChar(Address^);
    typePWIDECHAR: result := WideChar(PWideChar(Address^)^);
    typeWIDESTRING: result := WideString(Address^);

    typeSET: if Assigned(Scripter) then
    begin
      S := TByteSet(Address^);
      result := ByteSetToPaxArray(S, Scripter);
    end;

    typeRECORD:
    begin
      ClassRec := TPaxBaseScripter(Scripter).ClassList.FindClassByName(TypeName);
      if ClassRec = nil then
        raise TPaxScriptFailure(Format(errClassNotRegistered, [TypeName]));
      SO := ClassRec.CreateScriptObject;
      SO.ExtraPtr := Address;
      SO.ExternalExtraPtr := true;
      result := ScriptObjectToVariant(SO);
    end;

    typeARRAY:
    begin
      ClassRec := TPaxBaseScripter(Scripter).ClassList.FindClassByName(TypeName);
      if ClassRec = nil then
        raise TPaxScriptFailure(Format(errClassNotRegistered, [TypeName]));

      SO := ClassRec.CreateScriptObject;
      SO.Instance := SO;
      SO.ExtraPtr := Pointer(Address^);
      SO.ExternalExtraPtr := true;
      result := ScriptObjectToVariant(SO);
    end;

    typeCLASS:
    begin
      if not Assigned(Scripter) then
        Exit;
      Instance := TObject(Address^);

      if Assigned(Instance) then
      begin
        SO := DelphiInstanceToScriptObject(Instance, Scripter);
        result := ScriptObjectToVariant(SO);
      end
      else
        result := Variant(Address^);
    end;
  else
  begin
    Instance := TObject(Address^);

    if Assigned(Instance) then
    begin
      SO := DelphiInstanceToScriptObject(Instance, Scripter);
      result := ScriptObjectToVariant(SO);
    end
    else
      result := Variant(Address^);
  end
  end;
end;

procedure PutVariantValue(Scripter, Address: Pointer; const AValue: Variant; typeID: Integer);
var
  S: String;
  WS: WideString;
  VT, L: Integer;
  SS: ShortString;
  SO: TPaxScriptObject;
begin
  case TypeID of
    typeVARIANT: Variant(Address^) := AValue;
    typeOLEVARIANT: Variant(Address^) := AValue;
    typeBYTE: Byte(Address^) := AValue;
    typeENUM: Byte(Address^) := AValue;
    typeCHAR:
      begin
        S := AValue;
        Char(Address^) := S[1];
      end;
    typeBOOLEAN: Boolean(Address^) := AValue;
    typeWORDBOOL: WordBool(Address^) := AValue;
    typeLONGBOOL: LongBool(Address^) := AValue;
    typeINTEGER: Integer(Address^) := AValue;
    typeCARDINAL: Cardinal(Address^) := AValue;
    typePOINTER: Integer(Address^) := AValue;
    typeDOUBLE: Double(Address^) := AValue;
    typeSTRING: String(Address^) := AValue;
    typePCHAR: String(Address^) := AValue;
    typeWORD: Word(Address^) := AValue;
    typeSHORTINT: ShortInt(Address^) := AValue;
    typeSMALLINT: SmallInt(Address^) := AValue;
{$IFDEF VARIANTS}
    typeINT64: Int64(Address^) := varAsType(aValue, varInt64);
{$ELSE}
    typeINT64: Int64(Address^) := Integer(aValue);
{$ENDIF}
    typeSINGLE: Single(Address^) := AValue;
    typeCURRENCY: Currency(Address^) := AValue;
    typeCOMP: Comp(Address^) := AValue;
//    typeREAL48: Real48(Address^) := AValue;
    typeEXTENDED: Extended(Address^) := AValue;
    typeSHORTSTRING: ShortString(Address^) := AValue;
    typeWIDECHAR:
      begin
        WS := AValue;
        WideChar(Address^) := WS[1];
      end;
    typePWIDECHAR:
      begin
        WS := AValue;
        WideChar(PWideChar(Address^)^) := WS[1];
      end;
    typeWIDESTRING: WideString(Address^) := AValue;
    typeTVarRec:
    begin
      VT := VarType(AValue);
      case VT of
        varInteger:
          begin
            TVarRec(Address^).VType := vtInteger;
            TVarRec(Address^).VInteger := AValue;
          end;
        varDouble, varSingle:
          begin
            TVarRec(Address^).VType := vtExtended;
            GetMem(TVarRec(Address^).VExtended, SizeOf(Extended));
            TVarRec(Address^).VExtended^ := AValue;
          end;
        varString, VarOleStr:
          begin
           SS := AValue;
           L := Length(SS);
           TVarRec(Address^).VType := vtString;
           GetMem(TVarRec(Address^).VString, L + 1);
           Move(SS[1], TVarRec(Address^).VString^[1], L);
           TVarRec(Address^).VString^[0] := Chr(L);
          end;
        varBoolean:
          begin
           TVarRec(Address^).VType := vtBoolean;
           TVarRec(Address^).VBoolean := AValue;
          end;
      end;
    end;

    typeSET: if Assigned(Scripter) then
    begin
      TByteSet(Address^) := PaxArrayToByteSet(AValue);
    end;

    typeCLASS:
    begin
      if not Assigned(Scripter) then
        Exit;

      SO := VariantToScriptObject(AValue);
      TObject(Address^) := SO.Instance;
    end;
  else
  begin
    SO := VariantToScriptObject(AValue);
    TObject(Address^) := SO.Instance;
  end
  end;
end;

function DynamicArrayToVariant(Scripter, P: Pointer; const ArrayTypeName: string; ElTypeID: Integer): Variant;
var
  Q: Pointer;
  I, L, ElSize: Integer;
  SO: TPaxScriptObject;
  ClassRec: TPaxClassRec;
begin
  if P = nil then
    Exit;

  Q := ShiftPointer(P, - SizeOf(Integer));
  L := Integer(Q^);
  ElSize := PaxTypes.GetSize(ElTypeID);

  ClassRec := TPaxBaseScripter(scripter).ClassList.FindClassByName(ArrayTypeName);

  SO := ClassRec.CreateScriptObject();
  SO.Instance := SO;

  Q := AllocMem(2*SizeOf(Integer) +  L * ElSize);
  Integer(Q^) := 1;
  Q := ShiftPointer(Q, SizeOf(Integer));
  Integer(Q^) := L;
  Q := ShiftPointer(Q, SizeOf(Integer));
  SO.ExtraPtr := Q;
  SO.ExtraPtrSize := 2*SizeOf(Integer) +  L * ElSize;

  for I:=0 to L - 1 do
  begin
    case ElTypeId of
      typeCLASS, typeCLASSREF, typePOINTER, typeINTEGER, typeCARDINAL:
      begin
        Integer(Q^) := Integer(P^);
      end;
      typeDOUBLE:
      begin
        Double(Q^) := Double(P^);
      end;
      typeSINGLE:
      begin
        Single(Q^) := Single(P^);
      end;
      typeEXTENDED:
      begin
        Extended(Q^) := Extended(P^);
      end;
      typeBYTE, typeCHAR, typeBOOLEAN:
      begin
        Byte(Q^) := Byte(P^);
      end;
      typeSTRING:
      begin
        String(Q^) := String(P^);
      end;
      typeINT64:
      begin
        Int64(Q^) := Int64(P^);
      end;
      typeCurrency:
      begin
        Currency(Q^) := Currency(P^);
      end;
      typeVARIANT:
      begin
        Variant(Q^) := Variant(P^);
      end;
    end;
    Q := ShiftPointer(Q, ElSize);
    P := ShiftPointer(P, ElSize);
  end;

  result := ScriptObjectToVariant(SO);
end;

function VariantToDynamicArray(Scripter: Pointer; const V: Variant; ElTypeID: Integer): Pointer;
var
  L, I, ElSize: Integer;
  P: Pointer;
begin
  L := VarArrayHighBound(V, 1) + 1;
  ElSize := PaxTypes.GetSize(ElTypeID);
  result := AllocMem(2*SizeOf(Integer) +  L * ElSize);
  P := ShiftPointer(result, SizeOf(Integer));
  Integer(P^) := L;
  P := ShiftPointer(P, SizeOf(Integer));
  result := P;
  for I:=0 to L - 1 do
  begin
    PutVariantValue(Scripter, P, V[I], ElTypeID);
    P := ShiftPointer(P, ElSize);
  end;
end;

procedure EraseDynamicArray(Scripter, P: Pointer; ElTypeID: Integer);
var
  Q: Pointer;
  I, L, ElSize: Integer;
begin
  if P = nil then
    Exit;

  Q := ShiftPointer(P, - SizeOf(Integer));
  L := Integer(Q^);
  ElSize := PaxTypes.GetSize(ElTypeID);
  case ElTypeID of
    typeSTRING, typeWIDESTRING:
      for I:=0 to L - 1 do
      begin
        PutVariantValue(Scripter, P, '', ElTypeID);
        P := ShiftPointer(P, ElSize);
      end;
    typeVARIANT:
      for I:=0 to L - 1 do
      begin
        VarClear(Variant(P^));
        P := ShiftPointer(P, ElSize);
      end;
    typeOLEVARIANT:
      for I:=0 to L - 1 do
      begin
        VarClear(Variant(P^));
        P := ShiftPointer(P, ElSize);
      end;
    typeTVarRec:
      for I:=0 to L - 1 do
      begin
        case TVarRec(P^).VType of
          vtExtended: FreeMem(TVarRec(P^).VExtended, SizeOf(Extended));
          vtString: FreeMem(TVarRec(P^).VString, Length(TVarRec(P^).VString^) + 1);
        end;
        P := ShiftPointer(P, ElSize);
      end;
  end;
  Q := ShiftPointer(Q, - SizeOf(Integer));
  FreeMem(Q, 2*SizeOf(Integer) +  L * ElSize);
end;

function ToCurrency(const V: Variant): Currency;
begin
  result := V;
end;

end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?