NM64Decode.pas
上传用户:szzdds
上传日期:2013-09-18
资源大小:293k
文件大小:5k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit NM64Decode;
  2. interface
  3. uses
  4.   Classes;
  5. function B64Decode(const Source: TStream; var Destination: TStream): Boolean;
  6. implementation
  7. uses
  8.   sysutils;
  9. const
  10.   INVALID = $FF;
  11. var
  12.   B64_Table: array[0..255] of Byte;
  13. function B64Decode(const Source: TStream; var Destination: TStream): Boolean;
  14. const
  15.   EOD = '=';
  16.   EOB = $FE;
  17.   INVALID = $FF;
  18.   CR = #13;
  19.   LF = #10;
  20.   EOL = #0;
  21. var
  22.   Stream_Ptr: PChar;
  23.   procedure Decode;
  24.   var
  25.     Char1: Byte;
  26.     Char2: Byte;
  27.     Char3: Byte;
  28.     Char4: Byte;
  29.     Count: Integer;
  30.     Line_Ptr: PChar;
  31.     Line_Length: LongInt;
  32.     Line: string;
  33.   begin
  34.     Line_Length := StrLen(Stream_Ptr) * 3 div 4;
  35.     SetLength(Line, Line_Length);
  36.     Line_Ptr := PChar(Line);
  37.     while Line_Length > 0 do
  38.     begin
  39.       Count := 0;
  40.       if Stream_Ptr^ > EOL then
  41.       begin
  42.         Char1 := B64_Table[Byte(Stream_Ptr^)];
  43.         Inc(Stream_Ptr);
  44.       end
  45.       else
  46.         Char1 := INVALID;
  47.       if Stream_Ptr^ > EOL then
  48.       begin
  49.         Char2 := B64_Table[Byte(Stream_Ptr^)];
  50.         Inc(Stream_Ptr);
  51.       end
  52.       else
  53.         Char2 := INVALID;
  54.       if Stream_Ptr^ > EOL then
  55.       begin
  56.         Char3 := B64_Table[Byte(Stream_Ptr^)];
  57.         Inc(Stream_Ptr);
  58.       end
  59.       else
  60.         Char3 := INVALID;
  61.       if Stream_Ptr^ > EOL then
  62.       begin
  63.         Char4 := B64_Table[Byte(Stream_Ptr^)];
  64.         Inc(Stream_Ptr);
  65.       end
  66.       else
  67.         Char4 := INVALID;
  68.       if (Char1 = INVALID) or (Char2 = INVALID) then
  69.         raise Exception.Create('Invalid data encountered within stream')
  70.       else
  71.       begin
  72.         Line_Ptr^ := Char((Char1 shl 2) or ((Char2 and $30) shr 4));
  73.         Inc(Line_Ptr);
  74.         Inc(Count);
  75.         if (Char3 <> INVALID) then
  76.         begin
  77.           Line_Ptr^ := Char(((Char2 and $0F) shl 4) or ((Char3 and $3C) shr 2));
  78.           Inc(Line_Ptr);
  79.           Inc(Count);
  80.           if (Char4 <> INVALID) then
  81.           begin
  82.             Line_Ptr^ := Char(((Char3 and $03) shl 6) or (Char4));
  83.             Inc(Line_Ptr);
  84.             Inc(Count);
  85.           end;
  86.         end
  87.       end;
  88.       Dec(Line_Length, Count);
  89.     end;
  90.     Destination.Write(Pointer(Line)^, Line_Ptr - PChar(Line));
  91.   end;
  92. const
  93.   MaxBufSize = $FFFE;
  94. var
  95.   Buffer, FillPos, BufPos: PChar;
  96.   Counter, BytesRead: LongInt;
  97.   SourceSize: LongInt;
  98. begin
  99.   Result := TRUE;
  100. //  InitTable;
  101.   SourceSize := Source.Size;
  102.   Destination.Seek(0, soFromEnd);
  103.   Counter := 0;
  104.   GetMem(Buffer, MaxBufSize + 1);
  105.   FillPos := Buffer;
  106.   BufPos := Buffer;
  107.   Inc(FillPos, MaxBufSize + 1);
  108.   FillPos^ := EOL;
  109.   try
  110.     while (Source.Position < SourceSize) and (BufPos^ <> EOD) do
  111.     begin
  112.       FillPos := Buffer;
  113.       Inc(FillPos, Counter);
  114.       BytesRead := Source.Read(FillPos^, MaxBufSize - Counter);
  115.       Inc(Counter, BytesRead);
  116.       BufPos := Buffer;
  117.       Inc(FillPos, Counter);
  118.       FillPos^ := EOL;
  119.       Counter := 0;
  120.       while (BufPos^ <> EOL) do
  121.       begin
  122.         Stream_Ptr := BufPos;
  123.         while not (BufPos^ in [EOL, LF, CR, EOD]) do
  124.           Inc(BufPos);
  125.         if (BufPos^ <> EOL) or (BufPos^ = EOD) then
  126.         begin
  127.           BufPos^ := EOL;
  128.           Decode;
  129.           if BufPos^ = EOL then Inc(BufPos);
  130.           if BufPos^ = CR then Inc(BufPos);
  131.           if BufPos^ = LF then Inc(BufPos);
  132.         end
  133.         else
  134.         begin
  135.           Counter := BufPos - Stream_Ptr;
  136.           System.Move(Stream_Ptr^, Buffer^, Counter);
  137.           Break;
  138.         end;
  139.       end;
  140.     end;
  141.     if Counter > 0 then
  142.     begin
  143.       Stream_Ptr := Buffer;
  144.       Decode;
  145.     end;
  146.   finally
  147.     FreeMem(Buffer, MaxBufSize);
  148.   end;
  149. end;
  150. initialization
  151.   begin
  152.     FillChar(B64_Table, SizeOf(B64_Table), INVALID);
  153.     B64_Table[43] := 62;
  154.     B64_Table[47] := 63;
  155.     B64_Table[48] := 52;
  156.     B64_Table[49] := 53;
  157.     B64_Table[50] := 54;
  158.     B64_Table[51] := 55;
  159.     B64_Table[52] := 56;
  160.     B64_Table[53] := 57;
  161.     B64_Table[54] := 58;
  162.     B64_Table[55] := 59;
  163.     B64_Table[56] := 60;
  164.     B64_Table[57] := 61;
  165.     B64_Table[65] := 0;
  166.     B64_Table[66] := 1;
  167.     B64_Table[67] := 2;
  168.     B64_Table[68] := 3;
  169.     B64_Table[69] := 4;
  170.     B64_Table[70] := 5;
  171.     B64_Table[71] := 6;
  172.     B64_Table[72] := 7;
  173.     B64_Table[73] := 8;
  174.     B64_Table[74] := 9;
  175.     B64_Table[75] := 10;
  176.     B64_Table[76] := 11;
  177.     B64_Table[77] := 12;
  178.     B64_Table[78] := 13;
  179.     B64_Table[79] := 14;
  180.     B64_Table[80] := 15;
  181.     B64_Table[81] := 16;
  182.     B64_Table[82] := 17;
  183.     B64_Table[83] := 18;
  184.     B64_Table[84] := 19;
  185.     B64_Table[85] := 20;
  186.     B64_Table[86] := 21;
  187.     B64_Table[87] := 22;
  188.     B64_Table[88] := 23;
  189.     B64_Table[89] := 24;
  190.     B64_Table[90] := 25;
  191.     B64_Table[97] := 26;
  192.     B64_Table[98] := 27;
  193.     B64_Table[99] := 28;
  194.     B64_Table[100] := 29;
  195.     B64_Table[101] := 30;
  196.     B64_Table[102] := 31;
  197.     B64_Table[103] := 32;
  198.     B64_Table[104] := 33;
  199.     B64_Table[105] := 34;
  200.     B64_Table[106] := 35;
  201.     B64_Table[107] := 36;
  202.     B64_Table[108] := 37;
  203.     B64_Table[109] := 38;
  204.     B64_Table[110] := 39;
  205.     B64_Table[111] := 40;
  206.     B64_Table[112] := 41;
  207.     B64_Table[113] := 42;
  208.     B64_Table[114] := 43;
  209.     B64_Table[115] := 44;
  210.     B64_Table[116] := 45;
  211.     B64_Table[117] := 46;
  212.     B64_Table[118] := 47;
  213.     B64_Table[119] := 48;
  214.     B64_Table[120] := 49;
  215.     B64_Table[121] := 50;
  216.     B64_Table[122] := 51;
  217.   end;
  218. end.