cxvariants.pas

来自「胜天进销存源码,国产优秀的进销存」· PAS 代码 · 共 1,201 行 · 第 1/3 页

PAS
1,201
字号
      Result := D2.VType = varNull
    else
      if D2.VType in [varEmpty, varNull] then
        Result := False
      else
        Result := V1 = V2;
end;

{$ENDIF}

function VarIsSoftNull(const AValue: Variant): Boolean;
begin
  Result := VarIsNull(AValue) or
    ({(VarType(AValue) = varString)}VarIsStr(AValue) and (AValue = ''));
end;

function VarToStrEx(const V: Variant): string;
begin
  Result := VarToStr(V);
{$IFNDEF DELPHI6}
  if VarType(V) = varDouble then
    Result := StringReplace(Result, GetLocaleChar(GetThreadLocale, LOCALE_SDECIMAL, '.'),
      DecimalSeparator, []);
{$ENDIF}
end;

function VarTypeIsCurrency(AVarType: TVarType): Boolean;
begin
  Result := (AVarType = varCurrency)
  {$IFNDEF NONDB}
    {$IFDEF DELPHI6} or (AVarType = VarFMTBcd){$ENDIF}
  {$ENDIF};
end;

function VarBetweenArrayCreate(const AValue1, AValue2: Variant): Variant;
begin
  Result := VarArrayCreate([0, 1], varVariant);
  Result[0] := AValue1;
  Result[1] := AValue2;
end;

function VarListArrayCreate(const AValue: Variant): Variant;
begin
  Result := VarArrayCreate([0, 0], varVariant);
  Result[0] := AValue;
end;

procedure VarListArrayAddValue(var Value: Variant; const AValue: Variant);
var
  V: Variant;
  I, C: Integer;
begin
  C := VarArrayHighBound(Value, 1) - VarArrayLowBound(Value, 1) + 2;
  V := VarArrayCreate([0, C - 1], varVariant);
  for I := VarArrayLowBound(Value, 1) to VarArrayHighBound(Value, 1) do
    V[I] := Value[I];
  V[C - 1] := AValue;
  Value := V;
end;
        
// Stream routines

function ReadStringFunc(AStream: TStream): string;
begin
  ReadStringProc(AStream, Result);
end;

procedure ReadStringProc(AStream: TStream; var S: string);
var
  L: Integer;
begin
  AStream.ReadBuffer(L, SizeOf(L));
  SetLength(S, L);
  AStream.ReadBuffer(Pointer(S)^, L);
end;

procedure WriteStringProc(AStream: TStream; const S: string);
var
  L: Integer;
begin
  L := Length(S);
  AStream.WriteBuffer(L, SizeOf(L));
  AStream.WriteBuffer(S[1], L);
end;

function ReadWideStringFunc(AStream: TStream): WideString;
begin
  ReadWideStringProc(AStream, Result); 
end;

procedure ReadWideStringProc(AStream: TStream; var S: WideString);
var
  L: Integer;
begin
  AStream.ReadBuffer(L, SizeOf(L));
  SetLength(S, L);
  AStream.ReadBuffer(Pointer(S)^, L * 2);
end;

procedure WriteWideStringProc(AStream: TStream; const S: WideString);
var
  L: Integer;
begin
  L := Length(S);
  AStream.WriteBuffer(L, SizeOf(L));
  AStream.WriteBuffer(Pointer(S)^, L * 2);
end;

function ReadVariantFunc(AStream: TStream): Variant;
begin
  ReadVariantProc(AStream, Result);
end;

procedure ReadVariantProc(AStream: TStream; var Value: Variant);
const
  ValTtoVarT: array[TValueType] of Integer = (varNull, varError,
    {$IFNDEF DELPHI6}varByte{$ELSE}varShortInt{$ENDIF},
    varSmallInt, varInteger, varDouble, varString, varError, varBoolean,
    varBoolean, varError, varError, varString, varEmpty, varError, varSingle,
    varCurrency, varDate, varOleStr,
    {$IFDEF DELPHI6}varInt64{$ELSE}varError{$ENDIF}
    {$IFDEF DELPHI6}, varError {$IFDEF DELPHI8}, varDouble{$ENDIF}{$ENDIF});
var
  ValType: TValueType;

  function ReadValue: TValueType;
  var
    B: Byte;
  begin
    AStream.ReadBuffer(B, SizeOf(Byte));
    Result := TValueType(B);
  end;

  function ReadInteger: LargeInt;
  var
    SH: Shortint;
    SM: Smallint;
    I: Integer;
  begin
    case ValType of
      vaInt8:
        begin
          AStream.ReadBuffer(SH, SizeOf(SH));
          Result := SH;
        end;
      vaInt16:
        begin
          AStream.ReadBuffer(SM, SizeOf(SM));
          Result := SM;
        end;
  {$IFDEF DELPHI6}
      vaInt32:
  {$ELSE}
    else
  {$ENDIF}
      begin
        AStream.ReadBuffer(I, SizeOf(I));
        Result := I;
      end
  {$IFDEF DELPHI6}
    else  // vaInt64
      AStream.ReadBuffer(Result, SizeOf(Result));
  {$ENDIF}
    end;
  end;

  function ReadFloat: Extended;
  begin
    AStream.ReadBuffer(Result, SizeOf(Result));
  end;

  function ReadSingle: Single;
  begin
    AStream.ReadBuffer(Result, SizeOf(Result));
  end;

  function ReadCurrency: Currency;
  begin
    ReadCurrencyProc(AStream, Result);
  end;

  function ReadDate: TDateTime;
  begin
    ReadDateTimeProc(AStream, Result);
  end;

  function ReadString: string;
  var
    L: Integer;
  begin
    L := 0;
    case ValType of
      vaString:
        AStream.ReadBuffer(L, SizeOf(Byte));
    else {vaLString}
      AStream.ReadBuffer(L, SizeOf(Integer));
    end;
    SetString(Result, PChar(nil), L);
    AStream.ReadBuffer(Pointer(Result)^, L);
  end;

  function ReadWideString: WideString;
  begin
    ReadWideStringProc(AStream, Result);
  end;

  procedure ReadArrayProc(var Value: Variant);
  var
    I, C: Integer;
    V: Variant;
  begin
    // read size
    ValType := ReadValue; // len
    C := ReadInteger;
    // read values
    Value := VarArrayCreate([0, C - 1], varVariant);
    for I := 0 to C - 1 do
    begin
      ReadVariantProc(AStream, V);
      Value[I] := V;
    end;
  end;

begin
  ValType := ReadValue;
  if ValType = vaList then
  begin
    ReadArrayProc(Value);
    Exit;
  end;
  case ValType of
    vaNil:
      VarClear(Value);
    vaNull:
      Value := Null;
    vaInt8:
      {$IFNDEF DELPHI6}
      TVarData(Value).VByte := Byte(ReadInteger);
      {$ELSE}
      TVarData(Value).VShortInt := ShortInt(ReadInteger);
      {$ENDIF}
    vaInt16:
      TVarData(Value).VSmallint := Smallint(ReadInteger);
    vaInt32:
      TVarData(Value).VInteger := ReadInteger;
  {$IFDEF DELPHI6}
    vaInt64:
      TVarData(Value).VInt64 := ReadInteger;
  {$ENDIF}
    vaExtended:
      TVarData(Value).VDouble := ReadFloat;
    vaString, vaLString:
      Value := ReadString;
    vaFalse, vaTrue:
      TVarData(Value).VBoolean := ValType = vaTrue;
    vaWString:
      Value := ReadWideString;
    vaSingle:
      TVarData(Value).VSingle := ReadSingle;
    vaCurrency:
      TVarData(Value).VCurrency := ReadCurrency;
    vaDate:
      TVarData(Value).VDate := ReadDate;
  else
    raise EReadError.Create(cxSDataReadError);
  end;
  TVarData(Value).VType := ValTtoVarT[ValType];
end;

procedure WriteVariantProc(AStream: TStream; const AValue: Variant);

  procedure WriteValue(Value: TValueType);
  begin
    AStream.WriteBuffer(Byte(Value), SizeOf(Byte));
  end;

  procedure WriteInteger(Value: {$IFDEF DELPHI6}LargeInt{$ELSE}Integer{$ENDIF});
  var
    SH: Shortint;
    SM: Smallint;
    I: Integer;
  begin
    if (Value >= Low(ShortInt)) and (Value <= High(ShortInt)) then
    begin
      WriteValue(vaInt8);
      SH := Value;
      AStream.WriteBuffer(SH, SizeOf(SH));
    end
    else
      if (Value >= Low(SmallInt)) and (Value <= High(SmallInt)) then
      begin
        WriteValue(vaInt16);
        SM := Value;
        AStream.WriteBuffer(SM, SizeOf(SM));
      end
      else
      {$IFDEF DELPHI6}
        if (Value >= Low(Integer)) and (Value <= High(Integer)) then
      {$ENDIF}
        begin
          WriteValue(vaInt32);
          I := Value;
          AStream.WriteBuffer(I, SizeOf(I));
        end
      {$IFDEF DELPHI6}
        else
        begin
          WriteValue(vaInt64);
          AStream.WriteBuffer(Value, SizeOf(Value));
        end;
      {$ENDIF}
  end;

  procedure WriteString(const Value: string);
  var
    B: Byte;
    L: Integer;
  begin
    L := Length(Value);
    if L <= 255 then
    begin
      WriteValue(vaString);
      B := L;
      AStream.WriteBuffer(B, SizeOf(B));
    end
    else
    begin
      WriteValue(vaLString);
      AStream.WriteBuffer(L, SizeOf(L));
    end;
    AStream.WriteBuffer(Pointer(Value)^, L);
  end;

  procedure WriteFloat(const Value: Extended);
  begin
    WriteValue(vaExtended);
    AStream.WriteBuffer(Value, SizeOf(Extended));
  end;

  procedure WriteSingle(const Value: Single);
  begin
    WriteValue(vaSingle);
    AStream.WriteBuffer(Value, SizeOf(Single));
  end;
  
  procedure WriteCurrency(const Value: Currency);
  begin
    WriteValue(vaCurrency);
    WriteCurrencyProc(AStream, Value);
  end;
  
  procedure WriteDate(const Value: TDateTime);
  begin
    WriteValue(vaDate);
    WriteDateTimeProc(AStream, Value);
  end;

  procedure WriteWideString(const Value: WideString);
  begin
    WriteValue(vaWString);
    WriteWideStringProc(AStream, Value);
  end;

  procedure WriteArrayProc(const Value: Variant);
  var
    I, L, H: Integer;
  begin
    if VarArrayDimCount(Value) <> 1 then
      raise EWriteError.Create(cxSDataWriteError);
    L := VarArrayLowBound(Value, 1);
    H := VarArrayHighBound(Value, 1);
    WriteValue(vaList);
    WriteInteger(H - L + 1);
    for I := L to H do
      WriteVariantProc(AStream, Value[I]);
  end;

var
  VType: Integer;
begin
  if VarIsArray(AValue) then
  begin
    WriteArrayProc(AValue);
    Exit;
  end;
  VType := VarType(AValue);
  case VType and varTypeMask of
    varEmpty:
      WriteValue(vaNil);
    varNull:
      WriteValue(vaNull);
    varString:
      WriteString(AValue);
  {$IFDEF DELPHI6}
    varShortInt, varWord, varLongWord, varInt64,
  {$ENDIF}
    varByte, varSmallInt, varInteger:
      WriteInteger(AValue);
    varDouble:
      WriteFloat(AValue);
    varBoolean:

⌨️ 快捷键说明

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