二进制序列
keyValue.serialize.pas
/// <author>cxg 2023-8-16</author> /// 支持 delphi and fpc. /// 支持 linux and windows. /// 键-值 数据序列: keyLen(integer)+keyName(rawbytestring)+valueLen(integer)+value /// 测试: d7~d11,lazarus unit keyValue.serialize; interface uses FmtBcd, DateUtils, Variants, Classes, SysUtils; type {$IFNDEF fpc} {$IF RTLVersion<25} IntPtr = integer; {$IFEND IntPtr} {$IF CompilerVersion < 18}// before delphi 2007 TBytes = array of byte; {$IFEND} {$IFNDEF UNICODE} RawByteString = AnsiString; PRawByteString = ^RawByteString; {$ENDIF} {$ENDIF} TSerialize = class private fValue: TBytes; fKey: rawbytestring; fList: tlist; private procedure setInt(const keyName: rawbytestring; const Value: integer); procedure setStr(const keyName: rawbytestring; const Value: rawbytestring); procedure setVariant(const keyName: rawbytestring; const Value: variant); procedure setBytes(const keyName: rawbytestring; const Value: TBytes); procedure setDateTime(const keyName: rawbytestring; const Value: TDateTime); procedure setBool(const keyName: rawbytestring; const Value: boolean); procedure setSingle(const keyName: rawbytestring; const Value: single); procedure setDouble(const keyName: rawbytestring; const Value: double); procedure setByte(const keyName: rawbytestring; const Value: byte); procedure setInt64(const keyName: rawbytestring; const Value: int64); procedure setCurrency(const keyName: rawbytestring; const Value: Currency); procedure setStream(const keyName: rawbytestring; const Value: tstream); procedure setWord(const keyName: rawbytestring; const Value: word); procedure setExtended(const keyName: rawbytestring; const Value: Extended); procedure setLongWord(const keyName: rawbytestring; const Value: LongWord); procedure setShortint(const keyName: rawbytestring; const Value: Shortint); procedure setSmallint(const keyName: rawbytestring; const Value: Smallint); procedure setBCD(const keyName: rawbytestring; const Value: tbcd); private function getInt(const keyName: rawbytestring): integer; function getStr(const keyName: rawbytestring): rawbytestring; function getVariant(const keyName: rawbytestring): variant; function getBytes(const keyName: rawbytestring): TBytes; function getDateTime(const keyName: rawbytestring): TDateTime; function getBool(const keyName: rawbytestring): boolean; function getSingle(const keyName: rawbytestring): single; function getDouble(const keyName: rawbytestring): double; function getByte(const keyName: rawbytestring): byte; function getInt64(const keyName: rawbytestring): int64; function getCurrency(const keyName: rawbytestring): Currency; function getStream(const keyName: rawbytestring): tstream; function getWord(const keyName: rawbytestring): word; function getExtended(const keyName: rawbytestring): Extended; function getLongWord(const keyName: rawbytestring): LongWord; function getShortint(const keyName: rawbytestring): Shortint; function getSmallint(const keyName: rawbytestring): Smallint; function getBCD(const keyName: rawbytestring): tbcd; private function getCount: integer; public constructor Create; destructor Destroy; override; public function key(const keyName: rawbytestring): TSerialize; procedure Clear; function Delete(const keyName: rawbytestring): boolean; public procedure marshal(stream: TStream); function marshal2: TBytes; function marshal3: RawByteString; function marshal5: OleVariant; public procedure unMarshal(stream: TStream); overload; procedure unMarshal(bytes: TBytes); overload; procedure unMarshal(raw: RawByteString); overload; procedure unMarshal(ole: OleVariant); overload; public property asInt[const keyName: rawbytestring]: integer read getInt write setInt; property asStr[const keyName: rawbytestring]: rawbytestring read getStr write setStr; property AsVariant[const keyName: rawbytestring]: variant read getVariant write setVariant; property asBytes[const keyName: rawbytestring]: TBytes read getBytes write setBytes; property AsDateTime[const keyName: rawbytestring]: TDateTime read getDateTime write setDateTime; property asBool[const keyName: rawbytestring]: boolean read getBool write setBool; property asSingle[const keyName: rawbytestring]: single read getSingle write setSingle; property asDouble[const keyName: rawbytestring]: double read getDouble write setDouble; property asByte[const keyName: rawbytestring]: byte read getByte write setByte; property asInt64[const keyName: rawbytestring]: int64 read getInt64 write setInt64; property asCurrency[const keyName: rawbytestring]: Currency read getCurrency write setCurrency; property asStream[const keyName: rawbytestring]: tstream read getStream write setStream; property asWord[const keyName: rawbytestring]: word read getword write setword; property asExtended[const keyName: rawbytestring]: Extended read getExtended write setExtended; property asLongWord[const keyName: rawbytestring]: LongWord read getLongWord write setLongWord; property asShortint[const keyName: rawbytestring]: Shortint read getShortint write setShortint; property asSmallint[const keyName: rawbytestring]: Smallint read getSmallint write setSmallint; property asBCD[const keyName: rawbytestring]: tbcd read getBCD write setBCD; property asFloat[const keyName: rawbytestring]: double read getDouble write setDouble; property asCardinal[const keyName: rawbytestring]: LongWord read getLongWord write setLongWord; public property Count: integer read getCount; end; implementation function TSerialize.key(const keyName: rawbytestring): TSerialize; var i: integer; found: boolean; begin Result := nil; found := False; for i := 0 to fList.Count - 1 do begin if keyName = TSerialize(fList[i]).fKey then begin Result := TSerialize(fList[i]); exit; end; end; if not found then begin Result := TSerialize.Create; Result.fKey := keyName; fList.Add(Result); end; end; function TSerialize.getInt(const keyName: rawbytestring): integer; var ser: TSerialize; begin ser := key(keyName); Result := PInteger(ser.fValue)^; end; function TSerialize.getStr(const keyName: rawbytestring): rawbytestring; var len: integer; ser: TSerialize; begin ser := key(keyName); len := Length(ser.fValue); if len = 0 then Result := '' else begin SetLength(Result, len); Move(ser.FValue[0], PRawByteString(Result)^, len); end; end; function TSerialize.getStream(const keyName: rawbytestring): tstream; var ser: TSerialize; len: Integer; begin ser := key(keyName); len := Length(ser.fValue); Result := TMemoryStream.Create; Result.Size := len; Move(ser.fValue[0], TMemoryStream(Result).Memory^, len); Result.Position := 0; end; function TSerialize.getVariant(const keyName: rawbytestring): variant; var p: pbyte; len: integer; ser: TSerialize; begin ser := key(keyName); len := Length(ser.fValue); Result := VarArrayCreate([0, len - 1], varByte); p := VarArrayLock(Result); try Move(ser.fValue[0], p^, len); finally VarArrayUnlock(Result); end; end; function TSerialize.getWord(const keyName: rawbytestring): word; var ser: TSerialize; begin ser := key(keyName); Result := pword(ser.fValue)^; end; function TSerialize.getBytes(const keyName: rawbytestring): TBytes; var ser: TSerialize; begin ser := key(keyName); Result := ser.fValue; end; function TSerialize.getByte(const keyName: rawbytestring): byte; var ser: TSerialize; begin ser := key(keyName); Result := pbyte(ser.fValue)^; end; function TSerialize.getInt64(const keyName: rawbytestring): int64; var ser: TSerialize; begin ser := key(keyName); Result := PInt64(ser.fValue)^; end; function TSerialize.getLongWord(const keyName: rawbytestring): LongWord; var ser: TSerialize; begin ser := key(keyName); Result := PLongWord(ser.fValue)^; end; function TSerialize.getShortint(const keyName: rawbytestring): Shortint; var ser: TSerialize; begin ser := key(keyName); Result := PShortint(ser.fValue)^; end; function TSerialize.getSingle(const keyName: rawbytestring): single; var ser: TSerialize; begin ser := key(keyName); Result := PSingle(ser.fValue)^; end; function TSerialize.getSmallint(const keyName: rawbytestring): Smallint; var ser: TSerialize; begin ser := key(keyName); Result := PSmallint(ser.fValue)^; end; function TSerialize.getDateTime(const keyName: rawbytestring): TDateTime; var ser: TSerialize; begin ser := key(keyName); Result := PDateTime(ser.fValue)^; end; function TSerialize.getBool(const keyName: rawbytestring): boolean; var ser: TSerialize; begin ser := key(keyName); Result := PBoolean(ser.fValue)^; end; function TSerialize.getDouble(const keyName: rawbytestring): double; var ser: TSerialize; begin ser := key(keyName); Result := PDouble(ser.fValue)^; end; function TSerialize.getExtended(const keyName: rawbytestring): Extended; var ser: TSerialize; begin ser := key(keyName); Result := PExtended(ser.fValue)^; end; function TSerialize.getCurrency(const keyName: rawbytestring): Currency; var ser: TSerialize; begin ser := key(keyName); Result := PCurrency(ser.fValue)^; end; procedure TSerialize.setDouble(const keyName: rawbytestring; const Value: double); var ser: TSerialize; begin ser := key(keyName); SetLength(ser.fValue, SizeOf(double)); PDouble(ser.fValue)^ := Value; end; procedure TSerialize.setExtended(const keyName: rawbytestring; const Value: Extended); var ser: TSerialize; begin ser := key(keyName); SetLength(ser.fValue, SizeOf(Extended)); PExtended(ser.fValue)^ := Value; end; procedure TSerialize.setInt(const keyName: rawbytestring; const Value: integer); var ser: TSerialize; begin ser := key(keyName); SetLength(ser.fValue, SizeOf(integer)); PInteger(ser.fValue)^ := Value; end; procedure TSerialize.setShortint(const keyName: rawbytestring; const Value: Shortint); var ser: TSerialize; begin ser := key(keyName); SetLength(ser.fValue, SizeOf(Shortint)); PShortint(ser.fValue)^ := Value; end; procedure TSerialize.setSingle(const keyName: rawbytestring; const Value: single); var ser: TSerialize; begin ser := key(keyName); SetLength(ser.fValue, SizeOf(single)); PSingle(ser.fValue)^ := Value; end; procedure TSerialize.setSmallint(const keyName: rawbytestring; const Value: Smallint); var ser: TSerialize; begin ser := key(keyName); SetLength(ser.fValue, SizeOf(Smallint)); PSmallint(ser.fValue)^ := Value; end; procedure TSerialize.setStr(const keyName: rawbytestring; const Value: rawbytestring); var len: integer; ser: TSerialize; begin ser := key(keyName); len := Length(Value); SetLength(ser.fValue, len); if len > 0 then Move(PRawByteString(Value)^, ser.fValue[0], len); end; procedure TSerialize.setStream(const keyName: rawbytestring; const Value: tstream); var ser: TSerialize; begin ser := key(keyName); SetLength(ser.fValue, Value.Size); Value.Position := 0; Move(TMemoryStream(Value).Memory^, ser.fValue[0], Value.Size); end; procedure TSerialize.setVariant(const keyName: rawbytestring; const Value: variant); var p: pbyte; len: integer; ser: TSerialize; begin ser := key(keyName); len := VarArrayHighBound(Value, 1) - VarArrayLowBound(Value, 1) + 1; p := VarArrayLock(Value); try SetLength(ser.fValue, len); Move(p^, ser.fValue[0], len); finally VarArrayUnlock(Value); end; end; procedure TSerialize.setWord(const keyName: rawbytestring; const Value: word); var ser: TSerialize; begin ser := key(keyName); SetLength(ser.fValue, SizeOf(word)); PWord(ser.fValue)^ := Value; end; procedure TSerialize.setBytes(const keyName: rawbytestring; const Value: TBytes); var ser: TSerialize; begin ser := key(keyName); ser.fValue := Value; end; procedure TSerialize.setCurrency(const keyName: rawbytestring; const Value: Currency); var ser: TSerialize; begin ser := key(keyName); SetLength(ser.fValue, SizeOf(Currency)); pCurrency(ser.fValue)^ := Value; end; procedure TSerialize.setByte(const keyName: rawbytestring; const Value: byte); var ser: TSerialize; begin ser := key(keyName); SetLength(ser.fValue, SizeOf(byte)); pbyte(ser.fValue)^ := Value; end; procedure TSerialize.setInt64(const keyName: rawbytestring; const Value: int64); var ser: TSerialize; begin ser := key(keyName); SetLength(ser.fValue, SizeOf(int64)); PInt64(ser.fValue)^ := Value; end; procedure TSerialize.setLongWord(const keyName: rawbytestring; const Value: LongWord); var ser: TSerialize; begin ser := key(keyName); SetLength(ser.fValue, SizeOf(LongWord)); PLongWord(ser.fValue)^ := Value; end; procedure TSerialize.setDateTime(const keyName: rawbytestring; const Value: TDateTime); var ser: TSerialize; begin ser := key(keyName); SetLength(ser.fValue, SizeOf(TDateTime)); PDateTime(ser.fValue)^ := Value; end; procedure TSerialize.setBool(const keyName: rawbytestring; const Value: boolean); var ser: TSerialize; begin ser := key(keyName); SetLength(ser.fValue, SizeOf(boolean)); PBoolean(ser.fValue)^ := Value; end; procedure TSerialize.setBCD(const keyName: rawbytestring; const Value: tbcd); var ser: TSerialize; begin ser := key(keyName); SetLength(ser.fValue, SizeOf(TBcd)); PBcd(ser.fValue)^ := Value; end; procedure TSerialize.unMarshal(stream: TStream); var keyLen, len: integer; keyName: rawbytestring; ser: TSerialize; begin stream.Position := 0; while stream.Position < stream.Size do begin stream.Read(keyLen, SizeOf(Integer)); SetLength(keyName, keyLen); stream.Read(PRawByteString(keyName)^, keyLen); stream.Read(len, SizeOf(Integer)); ser := TSerialize.Create; SetLength(ser.fValue, len); stream.Read(ser.fValue[0], len); ser.fKey := keyName; fList.Add(ser); end; end; procedure TSerialize.unMarshal(ole: OleVariant); var keyLen, len, at: integer; keyName: rawbytestring; ser: TSerialize; p: pbyte; begin at := 0; p := VarArrayLock(ole); while at < VarArrayHighBound(ole, 1) do begin Move(p[at], keyLen, SizeOf(Integer)); inc(at, SizeOf(Integer)); SetLength(keyName, keyLen); Move(p[at], PRawByteString(keyName)^, keyLen); inc(at, keyLen); Move(p[at], len, SizeOf(Integer)); inc(at, SizeOf(Integer)); ser := TSerialize.Create; SetLength(ser.fValue, len); Move(p[at], ser.fValue[0], len); Inc(at, len); ser.fKey := keyName; fList.Add(ser); end; VarArrayUnlock(ole); end; procedure TSerialize.unMarshal(bytes: TBytes); var len, at: integer; keyName: rawbytestring; ser: TSerialize; begin at := 0; while at < Length(bytes) do begin Move(bytes[at], len, SizeOf(Integer)); inc(at, SizeOf(Integer)); SetLength(keyName, len); Move(bytes[at], PRawByteString(keyName)^, len); inc(at, len); Move(bytes[at], len, SizeOf(Integer)); inc(at, SizeOf(Integer)); ser := TSerialize.Create; SetLength(ser.fValue, len); Move(bytes[at], ser.fValue[0], len); inc(at, len); ser.fKey := keyName; fList.Add(ser); end; end; procedure TSerialize.unMarshal(raw: RawByteString); var len, at: integer; keyName: rawbytestring; ser: TSerialize; begin at := 0; while at < Length(raw) do begin if at = 0 then at := 1; Move(raw[at], len, SizeOf(Integer)); inc(at, SizeOf(Integer)); SetLength(keyName, len); Move(raw[at], PRawByteString(keyName)^, len); inc(at, len); Move(raw[at], len, SizeOf(Integer)); inc(at, SizeOf(Integer)); ser := TSerialize.Create; SetLength(ser.fValue, len); Move(raw[at], ser.fValue[0], len); inc(at, len); ser.fKey := keyName; fList.Add(ser); end; end; procedure TSerialize.marshal(stream: TStream); var i: integer; ser: TSerialize; len: integer; begin stream.Position := 0; for i := 0 to fList.Count - 1 do begin ser := TSerialize(fList[i]); len := Length(ser.fKey); stream.Write(len, SizeOf(Integer)); stream.Write(prawbytestring(ser.fKey)^, len); len := Length(ser.fValue); stream.Write(len, SizeOf(Integer)); stream.Write(ser.fValue[0], len); end; end; function TSerialize.marshal2: TBytes; var i, at, len: integer; ser: TSerialize; keyLen, valueLen: integer; begin len := 0; for i := 0 to fList.Count - 1 do begin ser := TSerialize(fList[i]); keyLen := Length(ser.fKey); valueLen := Length(ser.fValue); inc(len, SizeOf(Integer) + keyLen + SizeOf(Integer) + valueLen); end; SetLength(Result, len); at := 0; for i := 0 to fList.Count - 1 do begin ser := TSerialize(fList[i]); keyLen := Length(ser.fKey); valueLen := Length(ser.fValue); Move(keyLen, Result[at], SizeOf(Integer)); inc(at, SizeOf(Integer)); Move(prawbytestring(ser.fKey)^, Result[at], keyLen); inc(at, keyLen); Move(valueLen, Result[at], SizeOf(Integer)); inc(at, SizeOf(Integer)); Move(ser.fValue[0], Result[at], valueLen); inc(at, valueLen); end; end; function TSerialize.marshal5: OleVariant; var len, keyLen, valueLen, i, at: Integer; ser: TSerialize; p: pbyte; begin len := 0; for i := 0 to fList.Count - 1 do begin ser := TSerialize(fList[i]); keyLen := Length(ser.fKey); valueLen := Length(ser.fValue); inc(len, SizeOf(Integer) + keyLen + SizeOf(Integer) + valueLen); end; Result := VarArrayCreate([0, len - 1], varByte); at := 0; p := VarArrayLock(Result); for i := 0 to fList.Count - 1 do begin ser := TSerialize(fList[i]); keyLen := Length(ser.fKey); valueLen := Length(ser.fValue); Move(keyLen, p[at], SizeOf(Integer)); inc(at, SizeOf(Integer)); Move(prawbytestring(ser.fKey)^, p[at], keyLen); inc(at, keyLen); Move(valueLen, p[at], SizeOf(Integer)); inc(at, SizeOf(Integer)); Move(ser.fValue[0], p[at], valueLen); inc(at, valueLen); end; VarArrayUnlock(Result); end; function TSerialize.marshal3: RawByteString; var i, at, len: integer; ser: TSerialize; keyLen, valueLen: integer; begin len := 0; for i := 0 to fList.Count - 1 do begin ser := TSerialize(fList[i]); keyLen := Length(ser.fKey); valueLen := Length(ser.fValue); inc(len, SizeOf(Integer) + keyLen + SizeOf(Integer) + valueLen); end; SetLength(Result, len); at := 0; for i := 0 to fList.Count - 1 do begin ser := TSerialize(fList[i]); keyLen := Length(ser.fKey); valueLen := Length(ser.fValue); if at = 0 then at := 1; Move(keyLen, Result[at], SizeOf(Integer)); inc(at, SizeOf(Integer)); Move(PRawByteString(ser.fKey)^, Result[at], keyLen); inc(at, keyLen); Move(valueLen, Result[at], SizeOf(Integer)); inc(at, SizeOf(Integer)); Move(ser.fValue[0], Result[at], valueLen); inc(at, valueLen); end; end; procedure TSerialize.Clear; var i: integer; begin for i := fList.Count - 1 downto 0 do begin TSerialize(fList[i]).Free; fList.Delete(i); end; end; constructor TSerialize.Create; begin fList := TList.Create; end; function TSerialize.Delete(const keyName: rawbytestring): boolean; var i: integer; begin Result := False; for i := fList.Count - 1 downto 0 do begin if TSerialize(fList[i]).fKey = keyName then begin TSerialize(fList[i]).Free; fList.Delete(i); Result := True; end; end; end; destructor TSerialize.Destroy; begin Self.Clear; fList.Free; inherited; end; function TSerialize.getCount: integer; begin Result := fList.Count; end; function TSerialize.getBCD(const keyName: rawbytestring): TBcd; var ser: TSerialize; begin ser := key(keyName); Result := PBcd(ser.fValue)^; end; end.
标签:ser,二进制,TSerialize,len,keyName,序列,SizeOf,fValue From: https://www.cnblogs.com/hnxxcxg/p/17986751