sys.data.pas

sys.data.pas

复制代码
unit sys.data;
// cxg 2024-12-22 key-value list
// fit (fpc+delphi)
{$ifdef fpc}
{$mode delphi}{$H+}
{$endif}

interface

uses Generics.Collections, Variants, SysUtils, Classes;

type
  raw = RawByteString;
  Praw = PRawByteString;
  int = integer;

  Tdata = class
  private
    key: raw; // The key must be unique
    val: TBytes; // value
  private
    list: TList<Tdata>;
  private
    function path(const key: raw): Tdata;
    function getByteCnt: int;
  private
    function getI(const key: raw): int;
    procedure setI(const key: raw; const Value: int);
    function getI64(const key: raw): Int64;
    procedure setI64(const key: raw; const Value: Int64);
    function getB(const key: raw): boolean;
    procedure setB(const key: raw; const Value: boolean);
    function getD(const key: raw): Double;
    procedure setD(const key: raw; const Value: Double);
    function getS(const key: raw): raw;
    procedure setS(const key, Value: raw);
    function getV(const key: raw): Variant;
    procedure setV(const key: raw; const Value: Variant);
    function getST(const key: raw): TStream;
    procedure setST(const key: raw; const Value: TStream);
  public
    property I[const key: raw]: int read getI write setI;
    property I64[const key: raw]: Int64 read getI64 write setI64;
    property B[const key: raw]: boolean read getB write setB;
    property D[const key: raw]: Double read getD write setD;
    property S[const key: raw]: raw read getS write setS;
    property V[const key: raw]: Variant read getV write setV;
    property ST[const key: raw]: TStream read getST write setST;
  public // marshal
    procedure toStream(stream: TStream);
    function toRaw: raw;
    function toBytes: TBytes;
  public // unmarshal
    procedure fromStream(stream: TStream);
    procedure fromRaw(const val: raw);
    procedure fromBytes(const val: TBytes);
  public
    constructor Create;
    destructor Destroy; override;
    procedure clear; // clear list;
  end;

implementation

procedure Tdata.clear;
begin
  while list.Count > 0 do
  begin
    list[0].free;
    list.Delete(0);
  end;
end;

constructor Tdata.Create;
begin
  list := TList<Tdata>.Create;
end;

destructor Tdata.Destroy;
begin
  clear;
  FreeAndNil(list);
end;

function Tdata.path(const key: raw): Tdata;
var
  I: int;
  found: boolean;
begin
  Result := nil;
  found := False;
  for I := 0 to list.Count - 1 do
  begin
    if key = list[I].key then
    begin
      Result := list[I];
      exit;
    end;
  end;
  if not found then
  begin
    Result := Tdata.Create;
    Result.key := key;
    list.Add(Result);
  end;
end;

procedure Tdata.fromBytes(const val: TBytes);
var
  data: Tdata;
  pos, len: int;
  key: raw;
begin
  pos := 0;
  while pos < length(val) do
  begin
    Move(val[pos], len, SizeOf(int));
    pos := pos + SizeOf(int);
    SetLength(key, len);
    Move(val[pos], Praw(key)^, len);
    pos := pos + len;
    Move(val[pos], len, SizeOf(int));
    pos := pos + SizeOf(int);
    data := Tdata.Create;
    SetLength(data.val, len);
    Move(val[pos], pbyte(data.val)^, len);
    pos := pos + len;
    data.key := key;
    list.Add(data);
  end;
end;

procedure Tdata.fromRaw(const val: raw);
var
  data: Tdata;
  pos, len: int;
  key: raw;
begin
  pos := 1;
  while pos < length(val) do
  begin
    Move(val[pos], len, SizeOf(int));
    pos := pos + SizeOf(int);
    SetLength(key, len);
    Move(val[pos], Praw(key)^, len);
    pos := pos + len;
    Move(val[pos], len, SizeOf(int));
    pos := pos + SizeOf(int);
    data := Tdata.Create;
    SetLength(data.val, len);
    Move(val[pos], pbyte(data.val)^, len);
    pos := pos + len;
    data.key := key;
    list.Add(data);
  end;
end;

procedure Tdata.fromStream(stream: TStream);
var
  len: int;
  key: raw;
  data: Tdata;
begin
  stream.Position := 0;
  while stream.Position < stream.size do
  begin
    stream.Read(len, SizeOf(int));
    SetLength(key, len);
    stream.Read(Praw(key)^, len);
    stream.Read(len, SizeOf(int));
    data := Tdata.Create;
    SetLength(data.val, len);
    stream.Read(pbyte(data.val)^, len);
    data.key := key;
    list.Add(data);
  end;
end;

function Tdata.getB(const key: raw): boolean;
var
  data: Tdata;
begin
  data := path(key);
  Result := PBoolean(data.val)^;
end;

function Tdata.getD(const key: raw): Double;
var
  data: Tdata;
begin
  data := path(key);
  Result := PDouble(data.val)^;
end;

function Tdata.getI(const key: raw): integer;
var
  data: Tdata;
begin
  data := path(key);
  Result := PInteger(data.val)^;
end;

function Tdata.getI64(const key: raw): Int64;
var
  data: Tdata;
begin
  data := path(key);
  Result := PInt64(data.val)^;
end;

function Tdata.getS(const key: raw): raw;
var
  data: Tdata;
  len: int;
begin
  data := path(key);
  len := length(data.val);
  if len = 0 then
    Result := ''
  else
  begin
    SetLength(Result, len);
    Move(pbyte(data.val)^, Praw(Result)^, len);
  end;
end;

function Tdata.getByteCnt: integer;
var
  I: int;
begin
  Result := 0;
  for I := 0 to list.Count - 1 do
    Result := Result + SizeOf(int) * 2 + length(list[I].key) +
      length(list[I].val);
end;

function Tdata.getST(const key: raw): TStream;
var
  data: Tdata;
  len: int;
begin
  data := path(key);
  len := length(data.val);
  Result := TMemoryStream.Create;
  Result.size := len;
  Result.Write(pbyte(data.val)^, len);
  Result.Position := 0;
end;

function Tdata.getV(const key: raw): Variant;
var
  p: pbyte;
  len: int;
  data: Tdata;
begin
  data := path(key);
  len := length(data.val);
  Result := VarArrayCreate([0, len - 1], varByte);
  p := VarArrayLock(Result);
  try
    Move(pbyte(data.val)^, p^, len);
  finally
    VarArrayUnlock(Result);
  end;
end;

procedure Tdata.setB(const key: raw; const Value: boolean);
var
  data: Tdata;
begin
  data := path(key);
  SetLength(data.val, SizeOf(boolean));
  PBoolean(data.val)^ := Value;
end;

procedure Tdata.setD(const key: raw; const Value: Double);
var
  data: Tdata;
begin
  data := path(key);
  SetLength(data.val, SizeOf(Double));
  PDouble(data.val)^ := Value;
end;

procedure Tdata.setI(const key: raw; const Value: integer);
var
  data: Tdata;
begin
  data := path(key);
  SetLength(data.val, SizeOf(int));
  PInteger(data.val)^ := Value;
end;

procedure Tdata.setI64(const key: raw; const Value: Int64);
var
  data: Tdata;
begin
  data := path(key);
  SetLength(data.val, SizeOf(Int64));
  PInt64(data.val)^ := Value;
end;

procedure Tdata.setS(const key, Value: raw);
var
  len: int;
  data: Tdata;
begin
  data := path(key);
  len := length(Value);
  SetLength(data.val, len);
  if len > 0 then
    Move(Praw(Value)^, pbyte(data.val)^, len);
end;

procedure Tdata.setST(const key: raw; const Value: TStream);
var
  data: Tdata;
begin
  data := path(key);
  SetLength(data.val, Value.size);
  Value.Position := 0;
  Value.Read(pbyte(data.val)^, Value.size);
  Value.Position := 0;
end;

procedure Tdata.setV(const key: raw; const Value: Variant);
var
  p: pbyte;
  len: int;
  data: Tdata;
begin
  data := path(key);
  len := VarArrayHighBound(Value, 1) - VarArrayLowBound(Value, 1) + 1;
  p := VarArrayLock(Value);
  try
    SetLength(data.val, len);
    Move(p^, pbyte(data.val)^, len);
  finally
    VarArrayUnlock(Value);
  end;
end;

function Tdata.toBytes: TBytes;
var
  I, len, pos: int;
begin
  SetLength(Result, getByteCnt);
  pos := 0;
  for I := 0 to list.Count - 1 do
  begin
    len := length(list[I].key);
    Move(len, Result[pos], SizeOf(int));
    pos := pos + SizeOf(int);
    Move(Praw(list[I].key)^, Result[pos], len);
    pos := pos + len;
    len := length(list[I].val);
    Move(len, Result[pos], SizeOf(int));
    pos := pos + SizeOf(int);
    Move(pbyte(list[I].val)^, Result[pos], len);
    pos := pos + len;
  end;
end;

function Tdata.toRaw: raw;
var
  I, len, pos: int;
begin
  SetLength(Result, getByteCnt);
  pos := 1;
  for I := 0 to list.Count - 1 do
  begin
    len := length(list[I].key);
    Move(len, Result[pos], SizeOf(int));
    pos := pos + SizeOf(int);
    Move(Praw(list[I].key)^, Result[pos], len);
    pos := pos + len;
    len := length(list[I].val);
    Move(len, Result[pos], SizeOf(int));
    pos := pos + SizeOf(int);
    Move(pbyte(list[I].val)^, Result[pos], len);
    pos := pos + len;
  end;
end;

procedure Tdata.toStream(stream: TStream);
var
  I, len: int;
begin
  stream.Position := 0;
  for I := 0 to list.Count - 1 do
  begin
    len := length(list[I].key);
    stream.Write(len, SizeOf(int));
    stream.Write(Praw(list[I].key)^, len);
    len := length(list[I].val);
    stream.Write(len, SizeOf(int));
    stream.Write(pbyte(list[I].val)^, len);
  end;
  stream.Position := 0;
end;

end.
复制代码

 

posted @   delphi中间件  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2021-01-04 Murmurhash 哈希算法
2017-01-04 mormot 数据集转换为JSON字串
2017-01-04 mormot orm rest注意事项
2017-01-04 mORMot 数据库操作
2017-01-04 mORMot使用基础
点击右上角即可分享
微信分享提示