mirror of
https://github.com/gentoo-mirror/guru.git
synced 2025-04-20 08:18:49 -04:00
225 lines
6.2 KiB
Diff
225 lines
6.2 KiB
Diff
changeset: 156:db1ee7036df0
|
|
user: Oliver Heimlich <oheim@posteo.de>
|
|
date: Tue Jul 07 22:46:46 2015 +0200
|
|
summary: base64decode.m: Cleanup of function code and fix of bug #38974
|
|
|
|
--- a/NEWS
|
|
+++ b/NEWS
|
|
@@ -1,3 +1,11 @@
|
|
+Summary of important user-visible changes for strings 1.2.1:
|
|
+-------------------------------------------------------------------
|
|
+
|
|
+ ** The function base64decode has been almost rewritten and no longer returns
|
|
+ trailing zeros which have been introduced by padding (bug #38974), returns
|
|
+ uint8 vectors instead of binary64 vectors, and should perform faster.
|
|
+
|
|
+
|
|
Summary of important user-visible changes for strings 1.2.0:
|
|
-------------------------------------------------------------------
|
|
|
|
--- a/inst/base64decode.m
|
|
+++ b/inst/base64decode.m
|
|
@@ -1,4 +1,5 @@
|
|
## Copyright (C) 2007 Muthiah Annamalai <muthiah.annamalai@uta.edu>
|
|
+## Copyright (C) 2015 Oliver Heimlich <oheim@posteo.de>
|
|
##
|
|
## This program is free software; you can redistribute it and/or modify it under
|
|
## the terms of the GNU General Public License as published by the Free Software
|
|
@@ -18,7 +19,8 @@
|
|
## @deftypefnx {Function File} {@var{rval} =} base64decode (@var{code}, @var{as_string})
|
|
## Convert a base64 @var{code} (a string of printable characters according to RFC 2045)
|
|
## into the original ASCII data set of range 0-255. If option @var{as_string} is
|
|
-## passed, the return value is converted into a string.
|
|
+## passed, the return value is converted into a string. Otherwise, the return
|
|
+## value is a uint8 row vector.
|
|
##
|
|
## @example
|
|
## @group
|
|
@@ -32,125 +34,84 @@
|
|
## @seealso {base64encode}
|
|
## @end deftypefn
|
|
|
|
-function z = base64decode (X, as_string)
|
|
- if (nargin < 1 )
|
|
+function Z = base64decode (X, as_string)
|
|
+ if (nargin < 1 || nargin > 2)
|
|
print_usage;
|
|
- elseif nargin == 1
|
|
- as_string=false;
|
|
+ elseif (nargin == 1)
|
|
+ as_string = false;
|
|
endif
|
|
|
|
- if ( any(X(:) < 0) || any(X(:) > 255))
|
|
- error("base64decode is expecting integers in the range 0 .. 255");
|
|
+ ## strip white space
|
|
+ X((X == ' ') | (X == "\n") | (X == "\r")) = [];
|
|
+
|
|
+ if (any (X(:) < 0) || any(X(:) > 255))
|
|
+ error ("base64decode is expecting integers in the range 0 .. 255");
|
|
endif
|
|
|
|
- ## decompose strings into the 4xN matrices
|
|
- ## formatting issues.
|
|
- if( rows(X) == 1 )
|
|
- Y=[];
|
|
- L=length(X);
|
|
- for z=4:4:L
|
|
- Y=[Y X(z-3:z)']; #keep adding columns
|
|
- end
|
|
- if min(size(Y))==1
|
|
- Y=reshape(Y,[L, 1]);
|
|
- else
|
|
- Y=reshape(Y,[4,L/4]);
|
|
- end
|
|
- X=Y;
|
|
- Y=[];
|
|
- end
|
|
-
|
|
- X = toascii(X);
|
|
- Xa= X;
|
|
-
|
|
- ## Work backwards. Starting at step in table,
|
|
- ## lookup the index of the element in the table.
|
|
+ ## convert into ascii code and 8 bit integers to save memory
|
|
+ X = uint8 (X);
|
|
|
|
- ## 6-bit encoding table, plus 1 for padding
|
|
- ## 26*2 + 10 + 2 + 1 = 64 + 1, '=' is EOF stop mark.
|
|
- table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
|
-
|
|
- S=size(X);
|
|
- SRows=S(1);
|
|
- SCols=S(2);
|
|
- Y=zeros(S);
|
|
-
|
|
- ## decode the incoming matrix &
|
|
+ ## decompose into the 4xN matrices - separation of encoded 3 byte blocks
|
|
+ if (rows (X) ~= 4)
|
|
+ if (rem (numel (X), 4) ~= 0)
|
|
+ error ("base64decode is expecting blocks of 4 characters to decode");
|
|
+ endif
|
|
+ X = reshape (X, [4, numel(X)./4]);
|
|
+ endif
|
|
+
|
|
+ ## decode 6-bit values from the incoming matrix &
|
|
## write the values into Va matrix.
|
|
- Va = -1*ones(size(Xa));
|
|
+ Va = ones (size(X), 'uint8') .* 65;
|
|
|
|
- iAZ = (Xa >= 'A').*(Xa <= 'Z') > 0;
|
|
- Va(iAZ)=Xa(iAZ)-'A';
|
|
-
|
|
- iaz = (Xa >= 'a').*(Xa <= 'z') > 0;
|
|
- Va(iaz)=Xa(iaz)-'a'+26;
|
|
+ iAZ = ((X >= 'A') & (X <= 'Z'));
|
|
+ Va(iAZ) = X(iAZ) - 'A';
|
|
|
|
- i09 = (Xa >= '0').*(Xa <= '9') > 0;
|
|
- Va(i09)=Xa(i09)-'0'+52;
|
|
+ iaz = ((X >= 'a') & (X <= 'z'));
|
|
+ Va(iaz) = X(iaz) - 'a' + 26;
|
|
|
|
- is = (Xa == '/') ; Va(is) = 63;
|
|
- ip = (Xa == '+') ; Va(ip) = 62;
|
|
- ieq = (Xa == '=') ; Va(ieq) = 0;
|
|
- clear is; clear ieq; clear ip; clear i09;
|
|
- clear iaz; clear iAZ; clear Xa; clear X;
|
|
+ i09 = ((X >= '0') & (X <= '9'));
|
|
+ Va(i09) = X(i09) - '0' + 52;
|
|
|
|
- Y=Va; clear Va;
|
|
- Y1=Y(1,:);
|
|
- if (SRows > 1)
|
|
- Y2=Y(2,:);
|
|
- else
|
|
- Y2=zeros(1,SCols);
|
|
- end;
|
|
-
|
|
- if (SRows > 2)
|
|
- Y3=Y(3,:);
|
|
- else
|
|
- Y3=zeros(1,SCols);
|
|
- end;
|
|
-
|
|
- if (SRows > 3)
|
|
- Y4=Y(4,:);
|
|
- else
|
|
- Y4=zeros(1,SCols);
|
|
- end;
|
|
+ Va(X == '+') = 62;
|
|
+ Va(X == '/') = 63;
|
|
+
|
|
+ padding = (X == '=');
|
|
+ Va(padding) = 0;
|
|
+
|
|
+ if (any (any (Va == 65)))
|
|
+ error ('base64decode is expecting valid characters A..Za..z0..9+/=');
|
|
+ endif
|
|
+
|
|
+ if (not (isempty (X)) && ...
|
|
+ (find (padding, 1) < numel (X) - 1 || ...
|
|
+ (X(end - 1) == '=' && X(end) ~= '=')))
|
|
+ error ('base64decode is expecting max two padding characters at the end');
|
|
+ endif
|
|
+
|
|
+ ## decode 4x6 bit into 3x8 bit
|
|
+ B = vertcat (...
|
|
+ Va(1, :) .* 4 + (Va(2, :) - rem (Va(2, :), 16)) ./ 16, ...
|
|
+ rem (Va(2, :), 16) .* 16 + (Va(3, :) - rem (Va(3, :), 4)) ./ 4, ...
|
|
+ rem (Va(3, :), 4) .* 64 + Va(4, :));
|
|
|
|
- ## +1 not required due to ASCII subtraction
|
|
- ## actual decoding work
|
|
- b1 = Y1*4 + fix(Y2/16);
|
|
- b2 = mod(Y2,16)*16+fix(Y3/4);
|
|
- b3 = mod(Y3,4)*64 + Y4;
|
|
-
|
|
- ZEROS=sum(sum(Y==0));
|
|
- L=length(b1)*3;
|
|
- z=zeros(1,L);
|
|
- z(1:3:end)=b1;
|
|
- if (SRows > 1)
|
|
- z(2:3:end)=b2;
|
|
- else
|
|
- z(2:3:end)=[];
|
|
- end;
|
|
-
|
|
- if (SRows > 2)
|
|
- z(3:3:end)=b3;
|
|
- else
|
|
- z(3:3:end)=[];
|
|
- end
|
|
-
|
|
- ## FIXME
|
|
- ## is this expected behaviour?
|
|
- if ( as_string )
|
|
- L=length(z);
|
|
- while ( ( L > 0) && ( z(L)==0 ) )
|
|
- L=L-1;
|
|
- end
|
|
- z=char(z(1:L));
|
|
+ ## Convert blocks into row vector
|
|
+ Z = B(:).';
|
|
+
|
|
+ ## Remove byte blocks which have been introduced by padding
|
|
+ if (not (isempty (X)))
|
|
+ Z(end - sum (padding(end - 1 : end)) + 1 : end) = [];
|
|
+ endif
|
|
+
|
|
+ if (as_string)
|
|
+ Z = char (Z);
|
|
end
|
|
|
|
endfunction
|
|
|
|
%!assert(base64decode(base64encode('Hakuna Matata'),true),'Hakuna Matata')
|
|
-%!assert(base64decode(base64encode([1:255])),[1:255])
|
|
+%!assert(base64decode(base64encode([1:255])),uint8([1:255]))
|
|
%!assert(base64decode(base64encode('taken'),true),'taken')
|
|
%!assert(base64decode(base64encode('sax'),true),'sax')
|
|
%!assert(base64decode(base64encode('H'),true),'H')
|
|
+%!assert(base64decode(base64encode('H'),false),uint8('H'))
|
|
%!assert(base64decode(base64encode('Ta'),true),'Ta')
|
|
|