|
34 | 34 | if (nargin == 0) |
35 | 35 | error('you must provide at least 1 input'); |
36 | 36 | end |
37 | | -if (exist('zmat', 'file') == 2 || exist('zmat', 'file') == 3) |
38 | | - output = zmat(varargin{1}, 0, 'base64'); |
39 | | - return |
40 | | -end |
41 | | - |
42 | | -jvmerr = javachk('jvm'); |
43 | | - |
44 | | -if (isoctavemesh || isempty(jvmerr)) |
45 | | - map = uint8(zeros(1, 256) + 65); |
46 | | - map(uint8(['A':'Z', 'a':'z', '0':'9', '+/='])) = 0:64; |
47 | | - map(uint8('-_')) = 62:63; |
48 | | - x = map(varargin{1}(:)); |
49 | | - |
50 | | - x(x > 64) = []; % remove non-base64 chars |
51 | | - x(x == 64) = []; % remove padding characters |
52 | 37 |
|
53 | | - nebytes = length(x); |
54 | | - nchunks = ceil(nebytes / 4); |
55 | | - if rem(nebytes, 4) > 0 |
56 | | - x(end + 1:4 * nchunks) = 0; |
| 38 | +% Try built-in JVM-based base64 decoder first (MATLAB with JVM only; |
| 39 | +% Octave's base64_decode is doubles-oriented, so we skip it here and use |
| 40 | +% the manual byte-oriented decoder as Octave's native path below). |
| 41 | +if (~isoctavemesh && usejava('jvm')) |
| 42 | + try |
| 43 | + rawinput = varargin{1}; |
| 44 | + if (ischar(rawinput)) |
| 45 | + rawinput = uint8(rawinput); |
| 46 | + end |
| 47 | + input = typecast(rawinput(:)', 'uint8'); |
| 48 | + output = typecast(org.apache.commons.codec.binary.Base64.decodeBase64(input), 'uint8')'; |
| 49 | + return |
| 50 | + catch |
| 51 | + % fall through to zmat |
57 | 52 | end |
58 | | - x = reshape(uint8(x), 4, nchunks); |
59 | | - output = repmat(uint8(0), 3, nchunks); |
| 53 | +end |
60 | 54 |
|
61 | | - output(1, :) = bitshift(x(1, :), 2); |
62 | | - output(1, :) = bitor(output(1, :), bitshift(x(2, :), -4)); |
63 | | - output(2, :) = bitshift(x(2, :), 4); |
64 | | - output(2, :) = bitor(output(2, :), bitshift(x(3, :), -2)); |
65 | | - output(3, :) = bitshift(x(3, :), 6); |
66 | | - output(3, :) = bitor(output(3, :), x(4, :)); |
| 55 | +% Fall back to ZMat toolbox when available |
| 56 | +nozmat = getvarfrom({'caller', 'base'}, 'NO_ZMAT'); |
67 | 57 |
|
68 | | - switch rem(nebytes, 4) |
69 | | - case 2 |
70 | | - output = output(1:end - 2); |
71 | | - case 3 |
72 | | - output = output(1:end - 1); |
| 58 | +if ((exist('zmat', 'file') == 2 || exist('zmat', 'file') == 3) && (isempty(nozmat) || nozmat == 0)) |
| 59 | + try |
| 60 | + output = zmat(varargin{1}, 0, 'base64'); |
| 61 | + return |
| 62 | + catch |
| 63 | + % zmat is on path but its zipmat MEX is missing or failed |
73 | 64 | end |
74 | | - output = output(:)'; |
75 | | - return |
76 | 65 | end |
77 | 66 |
|
78 | | -error(jvmerr); |
| 67 | +% Final fallback: pure-MATLAB/Octave manual decoder (byte-oriented) |
| 68 | +map = uint8(zeros(1, 256) + 65); |
| 69 | +map(uint8(['A':'Z', 'a':'z', '0':'9', '+/='])) = 0:64; |
| 70 | +map(uint8('-_')) = 62:63; |
| 71 | +x = map(varargin{1}(:)); |
| 72 | + |
| 73 | +x(x > 64) = []; % remove non-base64 chars |
| 74 | +x(x == 64) = []; % remove padding characters |
79 | 75 |
|
80 | | -if (ischar(varargin{1})) |
81 | | - varargin{1} = uint8(varargin{1}); |
| 76 | +nebytes = length(x); |
| 77 | +nchunks = ceil(nebytes / 4); |
| 78 | +if rem(nebytes, 4) > 0 |
| 79 | + x(end + 1:4 * nchunks) = 0; |
82 | 80 | end |
| 81 | +x = reshape(uint8(x), 4, nchunks); |
| 82 | +output = repmat(uint8(0), 3, nchunks); |
83 | 83 |
|
84 | | -input = typecast(varargin{1}(:)', 'uint8'); |
| 84 | +output(1, :) = bitshift(x(1, :), 2); |
| 85 | +output(1, :) = bitor(output(1, :), bitshift(x(2, :), -4)); |
| 86 | +output(2, :) = bitshift(x(2, :), 4); |
| 87 | +output(2, :) = bitor(output(2, :), bitshift(x(3, :), -2)); |
| 88 | +output(3, :) = bitshift(x(3, :), 6); |
| 89 | +output(3, :) = bitor(output(3, :), x(4, :)); |
85 | 90 |
|
86 | | -output = typecast(org.apache.commons.codec.binary.Base64.decodeBase64(input), 'uint8')'; |
| 91 | +switch rem(nebytes, 4) |
| 92 | + case 2 |
| 93 | + output = output(1:end - 2); |
| 94 | + case 3 |
| 95 | + output = output(1:end - 1); |
| 96 | +end |
| 97 | +output = output(:)'; |
0 commit comments