Browse Source

* Added ASCII85 encoder

git-svn-id: trunk@13441 -
michael 16 years ago
parent
commit
e888b92717
1 changed files with 146 additions and 0 deletions
  1. 146 0
      packages/fcl-base/src/ascii85.pp

+ 146 - 0
packages/fcl-base/src/ascii85.pp

@@ -73,9 +73,155 @@ type
   end;
 
   // TODO encoder...
+  TASCII85EncoderStream = class(TOwnerStream)
+  private
+    FPos,
+    FCount,
+    FTuple : Cardinal;
+    FWidth : Integer;
+    FBoundary : Boolean;
+  protected  
+    Procedure WriteBoundary;
+    Procedure Flush;
+    procedure Encode;
+  public
+    Constructor Create(ADest: TStream; AWidth : Integer = 72; ABoundary : Boolean = False); 
+    Destructor Destroy; Override;
+    function Write(Const aBuffer; aCount : longint) : longint; override;
+    Property Width : Integer Read FWidth;
+    Property Boundary : Boolean Read FBoundary;
+  end;                      
+        
 
 implementation
 
+{ TASCII85EncoderStream }
+
+Procedure TASCII85EncoderStream.WriteBoundary;
+
+Const
+  SBoundary = '<~';
+
+begin
+  Source.Write(SBoundary[1],2);
+  FPos:=2;
+end;
+
+Procedure TASCII85EncoderStream.Encode;
+
+Var
+  S : String[7];
+  I,J : Integer;
+  Buf : Array[0..4] of Byte;
+  
+begin
+  If (FTuple=0) then
+    begin
+    // Write 'z'
+    S:='z';
+    Inc(FPos);
+    If (FPos>FWidth) then
+      begin
+      S:=S+sLineBreak;
+      FPos:=0;
+      end;
+    end
+  else
+    begin  
+    For I:=0 to 4 do
+      begin
+      Buf[i]:=FTuple mod 85;
+      FTuple:=FTuple div 85;
+      end;
+    J:=0;  
+    S:='';
+    For I:=FCount+1 downto 0 do
+      begin
+      Inc(j);
+      S[J]:=Char(Buf[i]+Ord('!'));
+      SetLength(S,J);
+      Inc(FPos);
+      If (FPos>FWidth) then
+        begin
+        FPos:=0;
+        S:=S+sLinebreak;
+        J:=Length(S);
+        end;
+      end;
+    end;
+  Source.Write(S[1],Length(S));
+  FTuple:=0;
+  FCount:=-1;
+end;
+
+
+Procedure TASCII85EncoderStream.Flush;
+
+Const 
+  Boundary1 = '~>'+slinebreak;
+  Boundary2 = slinebreak+Boundary1;
+  
+Var
+  S : String;
+
+begin
+  If FCount>0 then
+    Encode;
+  If FBoundary then
+    begin
+    If FPos+2>FWidth then
+      S:=Boundary2
+    else
+      S:=Boundary1;
+    Source.Write(S[1],Length(S));
+    FBoundary:=False;
+    end;
+end;
+
+Constructor TASCII85EncoderStream.Create(ADest: TStream; AWidth : Integer = 72; ABoundary : Boolean = False);
+
+begin
+  Inherited Create(ADest);
+  FWidth:=AWidth;
+  FBoundary:=ABoundary;
+  If FBoundary then
+    WriteBoundary;
+end;
+
+Destructor TASCII85EncoderStream.Destroy; 
+
+begin
+  Flush;
+  Inherited;
+end;
+
+function TASCII85EncoderStream.Write(Const aBuffer; aCount : longint) : longint;
+
+Var
+  P : PByte;
+  C : Byte;
+  
+begin
+  P:=@Abuffer;  
+  Result:=ACount;
+  While ACount>0 do
+    begin
+    C:=P^;
+    Case FCount of
+      0 : FTuple:=FTuple or (C shl 24);
+      1 : FTuple:=FTuple or (C shl 16);
+      2 : FTuple:=FTuple or (C shl 8);
+      3 : begin
+          FTuple:=FTuple or C;
+          encode;
+          end;
+     end;     
+     Inc(FCount);
+     Inc(P);
+     Dec(ACount);
+     end;
+end;
+                     
 { TRingBuffer }
 
 function TASCII85RingBuffer.GetBufferSize() : Cardinal; inline;