procedure Encode6BitBuf(src, dest: PChar; srclen, destlen: Integer); procedure Decode6BitBuf(source: String; buf: PChar; buflen: integer); function EncodeStringMir(Str:String):String; function DecodeStringMir(str: String):String;
implementation
procedure Encode6BitBuf(src, dest: PChar; srclen, destlen: Integer); var i, restcount, destpos: integer; made, ch, rest: byte; begin try restcount := 0; rest := 0; destpos := 0; for i:=0 to srclen - 1 do begin if destpos >= destlen then break; ch := byte (src[i]); made := byte ((rest or (ch shr (2+restcount))) and $3F); rest := byte (((ch shl (8 - (2+restcount))) shr 2) and $3F); Inc (restcount, 2);
if restcount < 6 then begin dest[destpos] := char(made + $3C); Inc (destpos); end else begin if destpos < destlen-1 then begin dest[destpos] := char(made + $3C); dest[destpos+1] := char(rest + $3C); Inc (destpos, 2); end else begin dest[destpos] := char(made + $3C); Inc (destpos); end; restcount := 0; rest := 0; end; end; if restcount > 0 then begin dest[destpos] := char (rest + $3C); Inc (destpos); end; dest[destpos] := #0; except end; end;
procedure Decode6BitBuf(source: String; buf: PChar; buflen: integer); const Masks: array[2..6] of byte = ($FC, $F8, $F0, $E0, $C0); var i, len, bitpos, madebit, bufpos: Integer; ch, tmp, _byte: Byte; begin try Len := Length(source); bitpos := 2; madebit := 0; bufpos := 0; tmp := 0; for i:=1 to len do begin if Integer(source[i]) - $3C >= 0 then ch := Byte(source[i]) - $3C else begin bufpos := 0; break; end;
if bufpos >= buflen then break;
if (madebit+6) >= 8 then begin _byte := Byte(tmp or ((ch and $3F) shr (6-bitpos))); buf[bufpos] := Char(_byte); Inc (bufpos); madebit := 0; if bitpos < 6 then Inc (bitpos, 2) else begin bitpos := 2; continue; end; end; tmp := Byte (Byte(ch shl bitpos) and Masks[bitpos]); // #### ##-- Inc (madebit, 8-bitpos); end; buf [bufpos] := #0; except end; end;
function EncodeStringMir(Str:String):String; Var EncBuf : PChar; begin try GetMem(EncBuf, 51200); Encode6BitBuf(PChar(str), EncBuf, Length(str), 51200); Result := StrPas(EncBuf); finally FreeMem(EncBuf); end; end;
function DecodeStringMir(str:String):String; Var EncBuf: PChar; begin try GetMem(EncBuf, 51200); Decode6BitBuf(str, EncBuf, 51200); Result := StrPas(EncBuf); finally FreeMem(EncBuf); end; end;
procedure Encode6BitBuf(src, dest: PAnsiChar; srclen, destlen: Integer); var i, restcount, destpos: integer; made, ch, rest: byte; begin try restcount := 0; rest := 0; destpos := 0; for i := 0 to srclen - 1 do begin if destpos >= destlen then break;
ch := Byte(src[i]); made := Byte((rest or (ch shr (2 + restcount))) and $3F); rest := Byte(((ch shl (8 - (2 + restcount))) shr 2) and $3F); Inc(restcount, 2); if restcount < 6 then begin dest[destpos] := AnsiChar(made + $3C); Inc(destpos); end else begin if destpos < destlen - 1 then begin dest[destpos] := AnsiChar(made + $3C); dest[destpos + 1] := AnsiChar(rest + $3C); Inc(destpos, 2); end else begin dest[destpos] := AnsiChar(made + $3C); Inc(destpos); end; restcount := 0; rest := 0; end; end; if restcount > 0 then begin dest[destpos] := AnsiChar(rest + $3C); Inc(destpos); end; dest[destpos] := #0; except end; end;
procedure Decode6BitBuf(source: AnsiString; buf: PAnsiChar; buflen: integer); const Masks: array [2 .. 6] of byte = ($FC, $F8, $F0, $E0, $C0); var i, len, bitpos, madebit, bufpos: Integer; ch, tmp, _byte: Byte; begin try Len := Length(source); bitpos := 2; madebit := 0; bufpos := 0; tmp := 0; for i := 1 to len do begin if Integer(source[i]) - $3C < 0 then begin bufpos := 0; break; end;
if bufpos >= buflen then break;
ch := Byte(source[i]) - $3C;
if (madebit + 6) >= 8 then begin _byte := Byte(tmp or ((ch and $3F) shr (6 - bitpos))); buf[bufpos] := AnsiChar(_byte); Inc(bufpos); madebit := 0; if bitpos < 6 then Inc(bitpos, 2) else begin bitpos := 2; continue; end; end; tmp := Byte(Byte(ch shl bitpos) and Masks[bitpos]); // #### ##-- Inc(madebit, 8 - bitpos); end; buf[bufpos] := #0; except end; end;
function EncodeStringMir(Str: AnsiString): AnsiString; var EncBuf: PAnsiChar; begin GetMem(EncBuf, 51200); try Encode6BitBuf(PAnsiChar(str), EncBuf, Length(str), 51200); Result := EncBuf; finally FreeMem(EncBuf); end; end;
function DecodeStringMir(str: AnsiString): AnsiString; var EncBuf: PAnsiChar; begin GetMem(EncBuf, 51200); try Decode6BitBuf(str, EncBuf, 51200); Result := EncBuf; finally FreeMem(EncBuf); end; end;
procedure Encode6BitBuf(src, dest: TStream); var restcount: integer; _Byte, made, ch, rest: Byte; begin if src = nil then exit; if dest = nil then exit; restcount := 0; rest := 0; while src.Position < src.Size do begin src.Read(ch, 1); made := Byte((rest or (ch shr (2 + restcount))) and $3F); rest := Byte(((ch shl (8 - (2 + restcount))) shr 2) and $3F); Inc(restcount, 2); _Byte := made + $3C; if restcount < 6 then begin dest.Write(_Byte, 1); end else begin if True then //长度无限 begin dest.Write(_Byte, 1); _Byte := rest + $3C; dest.Write(_Byte, 1); end else begin dest.Write(_Byte, 1); end; restcount := 0; rest := 0; end; end; if restcount > 0 then begin _Byte := rest + $3C; dest.Write(_Byte, 1); end; end;
procedure Decode6BitBuf(src, dest: TStream); const Masks: array [2 .. 6] of byte = ($FC, $F8, $F0, $E0, $C0); var i, bitpos, madebit: Integer; ch, tmp, _byte: Byte; begin if src = nil then exit; if dest = nil then exit; bitpos := 2; madebit := 0; tmp := 0; while src.Position < src.Size do begin src.Read(ch, 1); ch := ch - $3C; if ch < 0 then break; if (madebit + 6) >= 8 then begin _byte := Byte(tmp or ((ch and $3F) shr (6 - bitpos))); dest.Write(_byte, 1); madebit := 0; if bitpos < 6 then Inc(bitpos, 2) else begin bitpos := 2; continue; end; end; tmp := Byte(Byte(ch shl bitpos) and Masks[bitpos]); // #### ##-- Inc(madebit, 8 - bitpos); end; end;
function EncodeStringMir(str: string; AEncoding: TEncoding = nil): string; var src, dest: TStringStream; begin if AEncoding = nil then AEncoding := TEncoding.UTF8; src := TStringStream.Create(str, AEncoding, False); dest := TStringStream.Create('', TEncoding.ASCII, False); try Encode6BitBuf(src, dest); Result := dest.DataString; finally FreeAndNil(src); FreeAndNil(dest); end; end;
function DecodeStringMir(str: string; AEncoding: TEncoding = nil): string; var src, dest: TStringStream; begin if AEncoding = nil then AEncoding := TEncoding.UTF8; src := TStringStream.Create(str, TEncoding.ASCII, False); dest := TStringStream.Create('', AEncoding, False); try Decode6BitBuf(src, dest); Result := dest.DataString; finally FreeAndNil(src); FreeAndNil(dest); end; end;