Unit P64; Interface { Similar to MIME base 64 or uuencode, but my own choice of characters and padding rules. This is the used with form encoded data. We have a binary string that we want to send as part of a Post request. We have specifically chosen characters that do not need to be encoded and decoded by RawUrlEncode. This makes the result shorter. Potentially the code is faster because we can skip the encode/decode step, but the standard tools will do that step anyway. Strictly speaking we don't need to use the form encoding for the POST data, but that's supported by the tools, like PHP. And presumably that's the safest thing to do for any HTTP proxy servers that we might not even know about. Another option would be to naively use the RawUrlEncode on the binary string. It should work, but the average size would be bigger. And the size would vary more, so if we are limited to a maximum size, we often will not get anywhere near that maximum size. That is to say that our worst case will be worse than our average case. "P" of course stands for "Phil". } Function Encode(Input : String) : String; Implementation Var EncodeAs : Array[0..63] Of Char; Function Encode(Input : String) : String; Var Q, R : Integer; FinalLength : Integer; // The length of the result. Position : Integer; // The encoding process is cyclic. The process for // the fourth byte is the same as for the first. InputIndex, OutputIndex : Integer; InProgress : Cardinal; Begin Q := Length(Input) Div 3; R := Length(Input) Mod 3; If R = 0 Then FinalLength := Q * 4 Else FinalLength := Q * 4 + Succ(R); // We always read in one extra byte of input, and this might cause exactly // the right output, or it might generate one extra byte. (Delphi always // adds a 0 to the end of the string. We process that byte just for // padding, in case the prevous byte was not competely written to the // output. SetLength(Result, Succ(FinalLength)); Position := 0; InProgress := 0; OutputIndex := 1; For InputIndex := 1 To Succ(Length(Input)) Do Begin InProgress := (InProgress ShL 8) Or Byte(Input[InputIndex]); Case Position Of 0: Begin Result[OutputIndex] := EncodeAs[(InProgress ShR 2) And 63]; Inc(OutputIndex); Position := 1 End; 1: Begin Result[OutputIndex] := EncodeAs[(InProgress ShR 4) And 63]; Inc(OutputIndex); Position := 2 End; 2: Begin Result[OutputIndex] := EncodeAs[(InProgress ShR 6) And 63]; Inc(OutputIndex); Result[OutputIndex] := EncodeAs[Inprogress And 63]; Inc(OutputIndex); Position := 0 End End End; SetLength(Result, FinalLength) End; Procedure InitializeTable; Var I : Integer; Procedure AddEntry(Ch : Char); Begin { AddEntry } EncodeAs[I] := Ch; Inc(I) End; { AddEntry } Var C : Char; Begin { InitializeTable } I := 0; For C := 'a' To 'z' Do AddEntry(C); For C := 'A' To 'Z' Do AddEntry(C); For C := '0' To '9' Do AddEntry(C); AddEntry('_'); AddEntry('-'); Assert(I = Succ(High(EncodeAs))) End; { InitializeTable } Initialization InitializeTable; End.