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.
标签:pas,const,val,pos,len,sys,key,data From: https://www.cnblogs.com/hnxxcxg/p/18652114