Home > atmlab > math > DataHash.m

DataHash

PURPOSE ^

DATAHASH - Checksum for Matlab array of any type

SYNOPSIS ^

function Hash = DataHash(Data, Opt)

DESCRIPTION ^

 DATAHASH - Checksum for Matlab array of any type
 This function creates a hash value for an input of any type. The type and
 dimensions of the input are considered as default, such that UINT8([0,0]) and
 UINT16(0) have different hash values. Nested STRUCTs and CELLs are parsed
 recursively.

 Hash = DataHash(Data, Opt)
 INPUT:
   Data: Array of these built-in types:
           (U)INT8/16/32/64, SINGLE, DOUBLE, (real or complex)
           CHAR, LOGICAL, CELL (nested), STRUCT (scalar or array, nested),
           function_handle.
   Opt:  Struct to specify the hashing algorithm and the output format.
         Opt and all its fields are optional.
         Opt.Method: String, known methods for Java 1.6 (Matlab 2009a):
              'SHA-1', 'SHA-256', 'SHA-384', 'SHA-512', 'MD2', 'MD5'.
            Known methods for Java 1.3 (Matlab 6.5):
              'MD5', 'SHA-1'.
            Default: 'MD5'.
         Opt.Format: String specifying the output format:
            'hex', 'HEX':      Lower/uppercase hexadecimal string.
            'double', 'uint8': Numerical vector.
            'base64':          Base64 encoded string, only printable
                               ASCII characters, 33% shorter than 'hex'.
            Default: 'hex'.
         Opt.Input: Type of the input as string, not case-sensitive:
             'array': The contents, type and size of the input [Data] are
                      considered  for the creation of the hash. Nested CELLs
                      and STRUCT arrays are parsed recursively. Empty arrays of
                      different type reply different hashs.
             'file':  [Data] is treated as file name and the hash is calculated
                      for the files contents.
             'bin':   [Data] is a numerical, LOGICAL or CHAR array. Only the
                      binary contents of the array is considered, such that
                      e.g. empty arrays of different type reply the same hash.
             Default: 'array'.

 OUTPUT:
   Hash: String, DOUBLE or UINT8 vector. The length depends on the hashing
         method.

 EXAMPLES:
 % Default: MD5, hex:
   DataHash([])                % 7de5637fd217d0e44e0082f4d79b3e73
 % MD5, Base64:
   Opt.Format = 'base64';
   Opt.Method = 'MD5';
   DataHash(int32(1:10), Opt)  % bKdecqzUpOrL4oxzk+cfyg
 % SHA-1, Base64:
   S.a = uint8([]);
   S.b = {{1:10}, struct('q', uint64(415))};
   Opt.Method = 'SHA-1';
   DataHash(S, Opt)            % ZMe4eUAp0G9TDrvSW0/Qc0gQ9/A
 % SHA-1 of binary values:
   Opt.Method = 'SHA-1';
   Opt.Input  = 'bin';
   DataHash(1:8, Opt)          % 826cf9d3a5d74bbe415e97d4cecf03f445f69225

 NOTE:
   Function handles and user-defined objects cannot be converted uniquely:
   - The subfunction ConvertFuncHandle uses the built-in function FUNCTIONS,
     but the replied struct can depend on the Matlab version.
   - It is tried to convert objects to UINT8 streams in the subfunction
     ConvertObject. A conversion by STRUCT() might be more appropriate.
   Adjust these subfunctions on demand.

   MATLAB CHARs have 16 bits! In consequence the string 'hello' is treated as
   UINT16('hello') for the binary input method.

   DataHash uses James Tursa's smart and fast TYPECASTX, if it is installed:
     http://www.mathworks.com/matlabcentral/fileexchange/17476
   As fallback the built-in TYPECAST is used automatically, but for large
   inputs this can be more than 100 times slower.
   For Matlab 6.5 installing typecastx is obligatory to run DataHash.

 Tested: Matlab 6.5, 7.7, 7.8, 7.13, WinXP/32, Win7/64
 Author: Jan Simon, Heidelberg, (C) 2011-2012 matlab.THISYEAR(a)nMINUSsimon.de

 See also: TYPECAST, CAST.
 FEX:
 Michael Kleder, "Compute Hash", no structs and cells:
   http://www.mathworks.com/matlabcentral/fileexchange/8944
 Tim, "Serialize/Deserialize", converts structs and cells to a byte stream:
   http://www.mathworks.com/matlabcentral/fileexchange/29457
 Jan Simon, "CalcMD5", MD5 only, faster C-mex, no structs and cells:
   http://www.mathworks.com/matlabcentral/fileexchange/25921

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

DOWNLOAD ^

DataHash.m

SOURCE CODE ^

0001 function Hash = DataHash(Data, Opt)
0002 % DATAHASH - Checksum for Matlab array of any type
0003 % This function creates a hash value for an input of any type. The type and
0004 % dimensions of the input are considered as default, such that UINT8([0,0]) and
0005 % UINT16(0) have different hash values. Nested STRUCTs and CELLs are parsed
0006 % recursively.
0007 %
0008 % Hash = DataHash(Data, Opt)
0009 % INPUT:
0010 %   Data: Array of these built-in types:
0011 %           (U)INT8/16/32/64, SINGLE, DOUBLE, (real or complex)
0012 %           CHAR, LOGICAL, CELL (nested), STRUCT (scalar or array, nested),
0013 %           function_handle.
0014 %   Opt:  Struct to specify the hashing algorithm and the output format.
0015 %         Opt and all its fields are optional.
0016 %         Opt.Method: String, known methods for Java 1.6 (Matlab 2009a):
0017 %              'SHA-1', 'SHA-256', 'SHA-384', 'SHA-512', 'MD2', 'MD5'.
0018 %            Known methods for Java 1.3 (Matlab 6.5):
0019 %              'MD5', 'SHA-1'.
0020 %            Default: 'MD5'.
0021 %         Opt.Format: String specifying the output format:
0022 %            'hex', 'HEX':      Lower/uppercase hexadecimal string.
0023 %            'double', 'uint8': Numerical vector.
0024 %            'base64':          Base64 encoded string, only printable
0025 %                               ASCII characters, 33% shorter than 'hex'.
0026 %            Default: 'hex'.
0027 %         Opt.Input: Type of the input as string, not case-sensitive:
0028 %             'array': The contents, type and size of the input [Data] are
0029 %                      considered  for the creation of the hash. Nested CELLs
0030 %                      and STRUCT arrays are parsed recursively. Empty arrays of
0031 %                      different type reply different hashs.
0032 %             'file':  [Data] is treated as file name and the hash is calculated
0033 %                      for the files contents.
0034 %             'bin':   [Data] is a numerical, LOGICAL or CHAR array. Only the
0035 %                      binary contents of the array is considered, such that
0036 %                      e.g. empty arrays of different type reply the same hash.
0037 %             Default: 'array'.
0038 %
0039 % OUTPUT:
0040 %   Hash: String, DOUBLE or UINT8 vector. The length depends on the hashing
0041 %         method.
0042 %
0043 % EXAMPLES:
0044 % % Default: MD5, hex:
0045 %   DataHash([])                % 7de5637fd217d0e44e0082f4d79b3e73
0046 % % MD5, Base64:
0047 %   Opt.Format = 'base64';
0048 %   Opt.Method = 'MD5';
0049 %   DataHash(int32(1:10), Opt)  % bKdecqzUpOrL4oxzk+cfyg
0050 % % SHA-1, Base64:
0051 %   S.a = uint8([]);
0052 %   S.b = {{1:10}, struct('q', uint64(415))};
0053 %   Opt.Method = 'SHA-1';
0054 %   DataHash(S, Opt)            % ZMe4eUAp0G9TDrvSW0/Qc0gQ9/A
0055 % % SHA-1 of binary values:
0056 %   Opt.Method = 'SHA-1';
0057 %   Opt.Input  = 'bin';
0058 %   DataHash(1:8, Opt)          % 826cf9d3a5d74bbe415e97d4cecf03f445f69225
0059 %
0060 % NOTE:
0061 %   Function handles and user-defined objects cannot be converted uniquely:
0062 %   - The subfunction ConvertFuncHandle uses the built-in function FUNCTIONS,
0063 %     but the replied struct can depend on the Matlab version.
0064 %   - It is tried to convert objects to UINT8 streams in the subfunction
0065 %     ConvertObject. A conversion by STRUCT() might be more appropriate.
0066 %   Adjust these subfunctions on demand.
0067 %
0068 %   MATLAB CHARs have 16 bits! In consequence the string 'hello' is treated as
0069 %   UINT16('hello') for the binary input method.
0070 %
0071 %   DataHash uses James Tursa's smart and fast TYPECASTX, if it is installed:
0072 %     http://www.mathworks.com/matlabcentral/fileexchange/17476
0073 %   As fallback the built-in TYPECAST is used automatically, but for large
0074 %   inputs this can be more than 100 times slower.
0075 %   For Matlab 6.5 installing typecastx is obligatory to run DataHash.
0076 %
0077 % Tested: Matlab 6.5, 7.7, 7.8, 7.13, WinXP/32, Win7/64
0078 % Author: Jan Simon, Heidelberg, (C) 2011-2012 matlab.THISYEAR(a)nMINUSsimon.de
0079 %
0080 % See also: TYPECAST, CAST.
0081 % FEX:
0082 % Michael Kleder, "Compute Hash", no structs and cells:
0083 %   http://www.mathworks.com/matlabcentral/fileexchange/8944
0084 % Tim, "Serialize/Deserialize", converts structs and cells to a byte stream:
0085 %   http://www.mathworks.com/matlabcentral/fileexchange/29457
0086 % Jan Simon, "CalcMD5", MD5 only, faster C-mex, no structs and cells:
0087 %   http://www.mathworks.com/matlabcentral/fileexchange/25921
0088 
0089 % $JRev: R-k V:011 Sum:kZG25iszfKbg Date:28-May-2012 12:48:06 $
0090 % $License: BSD (use/copy/change/redistribute on own risk, mention the author) $
0091 % $File: Tools\GLFile\DataHash.m $
0092 % History:
0093 % 001: 01-May-2011 21:52, First version.
0094 % 007: 10-Jun-2011 10:38, [Opt.Input], binary data, complex values considered.
0095 % 011: 26-May-2012 15:57, Fails for binary input and empty data.
0096 
0097 %{
0098 license:
0099 Copyright (c) 2011, Jan Simon
0100 All rights reserved.
0101 
0102 Redistribution and use in source and binary forms, with or without 
0103 modification, are permitted provided that the following conditions are 
0104 met:
0105 
0106     * Redistributions of source code must retain the above copyright 
0107       notice, this list of conditions and the following disclaimer.
0108     * Redistributions in binary form must reproduce the above copyright 
0109       notice, this list of conditions and the following disclaimer in 
0110       the documentation and/or other materials provided with the distribution
0111       
0112 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
0113 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
0114 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
0115 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
0116 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
0117 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
0118 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
0119 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
0120 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
0121 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
0122 POSSIBILITY OF SUCH DAMAGE.
0123 %}
0124 
0125 % Main function: ===============================================================
0126 % Java is needed:
0127 if ~usejava('jvm')
0128    error(['JSimon:', mfilename, ':NoJava'], ...
0129       '*** %s: Java is required.', mfilename);
0130 end
0131 
0132 % typecastx creates a shared data copy instead of the deep copy as Matlab's
0133 % TYPECAST - for a [1000x1000] DOUBLE array this is 100 times faster!
0134 persistent usetypecastx
0135 if isempty(usetypecastx)
0136    usetypecastx = ~isempty(which('typecastx'));  % Run the slow WHICH once only
0137 end
0138 
0139 % Default options: -------------------------------------------------------------
0140 Method    = 'MD5';
0141 OutFormat = 'hex';
0142 isFile    = false;
0143 isBin     = false;
0144 
0145 % Check number and type of inputs: ---------------------------------------------
0146 nArg = nargin;
0147 if nArg == 2
0148    if isa(Opt, 'struct') == 0   % Bad type of 2nd input:
0149       error(['JSimon:', mfilename, ':BadInput2'], ...
0150          '*** %s: 2nd input [Opt] must be a struct.', mfilename);
0151    end
0152    
0153    % Specify hash algorithm:
0154    if isfield(Opt, 'Method')
0155       Method = upper(Opt.Method);
0156    end
0157    
0158    % Specify output format:
0159    if isfield(Opt, 'Format')
0160       OutFormat = Opt.Format;
0161    end
0162    
0163    % Check if the Input type is specified - default: 'array':
0164    if isfield(Opt, 'Input')
0165       if strcmpi(Opt.Input, 'File')
0166          isFile = true;
0167          if ischar(Data) == 0
0168             error(['JSimon:', mfilename, ':CannotOpen'], ...
0169                '*** %s: 1st input is not a file name', mfilename);
0170          end
0171          
0172          if exist(Data, 'file') ~= 2
0173             error(['JSimon:', mfilename, ':FileNotFound'], ...
0174                '*** %s: File not found: %s.', mfilename, Data);
0175          end
0176          
0177       elseif strncmpi(Opt.Input, 'bin', 3)  % Accept 'binary'
0178          isBin = true;
0179          if (isnumeric(Data) || ischar(Data) || islogical(Data)) == 0
0180             error(['JSimon:', mfilename, ':BadDataType'], ...
0181                '*** %s: 1st input is not numeric, CHAR or LOGICAL.', mfilename);
0182          end
0183       end
0184    end
0185    
0186 elseif nArg ~= 1  % Bad number of arguments:
0187    error(['JSimon:', mfilename, ':BadNInput'], ...
0188       '*** %s: 1 or 2 inputs required.', mfilename);
0189 end
0190 
0191 % Create the engine: -----------------------------------------------------------
0192 try
0193    Engine = java.security.MessageDigest.getInstance(Method);
0194 catch
0195    error(['JSimon:', mfilename, ':BadInput2'], ...
0196       '*** %s: Invalid algorithm: [%s].', mfilename, Method);
0197 end
0198 
0199 % Create the hash value: -------------------------------------------------------
0200 if isFile
0201    % Read the file and calculate the hash:
0202    FID = fopen(Data, 'r');
0203    if FID < 0
0204       error(['JSimon:', mfilename, ':CannotOpen'], ...
0205          '*** %s: Cannot open file: %s.', mfilename, Data);
0206    end
0207    Data = fread(FID, Inf, '*uint8');
0208    fclose(FID);
0209    
0210    Engine.update(Data);
0211    if usetypecastx
0212       Hash = typecastx(Engine.digest, 'uint8');
0213    else
0214       Hash = typecast(Engine.digest, 'uint8');
0215    end
0216 
0217 elseif isBin             % Contents of an elementary array:
0218    if isempty(Data)      % Nothing to do, Engine.update fails for empty input!
0219       Hash = typecastx(Engine.digest, 'uint8');
0220    elseif usetypecastx   % Faster typecastx:
0221       if isreal(Data)
0222          Engine.update(typecastx(Data(:), 'uint8'));
0223       else
0224          Engine.update(typecastx(real(Data(:)), 'uint8'));
0225          Engine.update(typecastx(imag(Data(:)), 'uint8'));
0226       end
0227       Hash = typecastx(Engine.digest, 'uint8');
0228       
0229    else                  % Matlab's TYPECAST is less elegant:
0230       if isnumeric(Data)
0231          if isreal(Data)
0232             Engine.update(typecast(Data(:), 'uint8'));
0233          else
0234             Engine.update(typecast(real(Data(:)), 'uint8'));
0235             Engine.update(typecast(imag(Data(:)), 'uint8'));
0236          end
0237       elseif islogical(Data)               % TYPECAST cannot handle LOGICAL
0238          Engine.update(typecast(uint8(Data(:)), 'uint8'));
0239       elseif ischar(Data)                  % TYPECAST cannot handle CHAR
0240          Engine.update(typecast(uint16(Data(:)), 'uint8'));
0241          Engine.update(typecast(Data(:), 'uint8'));
0242       end
0243       Hash = typecast(Engine.digest, 'uint8');
0244    end
0245    
0246 elseif usetypecastx  % Faster typecastx:
0247    Engine = CoreHash_(Data, Engine);
0248    Hash   = typecastx(Engine.digest, 'uint8');
0249    
0250 else                 % Slower built-in TYPECAST:
0251    Engine = CoreHash(Data, Engine);
0252    Hash   = typecast(Engine.digest, 'uint8');
0253 end
0254 
0255 % Convert hash specific output format: -----------------------------------------
0256 switch OutFormat
0257    case 'hex'
0258       Hash = sprintf('%.2x', double(Hash));
0259    case 'HEX'
0260       Hash = sprintf('%.2X', double(Hash));
0261    case 'double'
0262       Hash = double(reshape(Hash, 1, []));
0263    case 'uint8'
0264       Hash = reshape(Hash, 1, []);
0265    case 'base64'
0266       Hash = fBase64_enc(double(Hash));
0267    otherwise
0268       error(['JSimon:', mfilename, ':BadOutFormat'], ...
0269          '*** %s: [Opt.Format] must be: HEX, hex, uint8, double, base64.', ...
0270          mfilename);
0271 end
0272 
0273 % return;
0274 
0275 % ******************************************************************************
0276 function Engine = CoreHash_(Data, Engine)
0277 % This mothod uses the faster typecastx version.
0278 
0279 % Consider the type and dimensions of the array to distinguish arrays with the
0280 % same data, but different shape: [0 x 0] and [0 x 1], [1,2] and [1;2],
0281 % DOUBLE(0) and SINGLE([0,0]):
0282 Engine.update([uint8(class(Data)), typecastx(size(Data), 'uint8')]);
0283 
0284 if isstruct(Data)                    % Hash for all array elements and fields:
0285    F      = sort(fieldnames(Data));  % Ignore order of fields
0286    Engine = CoreHash_(F, Engine);    % Catch the fieldnames
0287    
0288    for iS = 1:numel(Data)            % Loop over elements of struct array
0289       for iField = 1:length(F)       % Loop over fields
0290          Engine = CoreHash_(Data(iS).(F{iField}), Engine);
0291       end
0292    end
0293    
0294 elseif iscell(Data)                  % Get hash for all cell elements:
0295    for iS = 1:numel(Data)
0296       Engine = CoreHash_(Data{iS}, Engine);
0297    end
0298       
0299 elseif isnumeric(Data) || islogical(Data) || ischar(Data)
0300    if isempty(Data) == 0
0301       if isreal(Data)                % TRUE for LOGICAL and CHAR also:
0302          Engine.update(typecastx(Data(:), 'uint8'));
0303       else                           % typecastx accepts complex input:
0304          Engine.update(typecastx(real(Data(:)), 'uint8'));
0305          Engine.update(typecastx(imag(Data(:)), 'uint8'));
0306       end
0307    end
0308    
0309 elseif isa(Data, 'function_handle')
0310    Engine = CoreHash(ConvertFuncHandle(Data), Engine);
0311    
0312 else  % Most likely this is a user-defined object:
0313    try
0314       Engine = CoreHash(ConvertObject(Data), Engine);
0315    catch
0316       warning(['JSimon:', mfilename, ':BadDataType'], ...
0317          ['Type of variable not considered: ', class(Data)]);
0318    end
0319 end
0320 
0321 % return;
0322 
0323 % ******************************************************************************
0324 function Engine = CoreHash(Data, Engine)
0325 % This methods uses the slower TYPECAST of Matlab
0326 % See CoreHash_ for comments.
0327 
0328 Engine.update([uint8(class(Data)), typecast(size(Data), 'uint8')]);
0329 
0330 if isstruct(Data)                    % Hash for all array elements and fields:
0331    F      = sort(fieldnames(Data));  % Ignore order of fields
0332    Engine = CoreHash(F, Engine);     % Catch the fieldnames
0333    for iS = 1:numel(Data)            % Loop over elements of struct array
0334       for iField = 1:length(F)       % Loop over fields
0335          Engine = CoreHash(Data(iS).(F{iField}), Engine);
0336       end
0337    end
0338 elseif iscell(Data)                  % Get hash for all cell elements:
0339    for iS = 1:numel(Data)
0340       Engine = CoreHash(Data{iS}, Engine);
0341    end
0342 elseif isempty(Data)
0343 elseif isnumeric(Data)
0344    if isreal(Data)
0345       Engine.update(typecast(Data(:), 'uint8'));
0346    else
0347       Engine.update(typecast(real(Data(:)), 'uint8'));
0348       Engine.update(typecast(imag(Data(:)), 'uint8'));
0349    end
0350 elseif islogical(Data)               % TYPECAST cannot handle LOGICAL
0351    Engine.update(typecast(uint8(Data(:)), 'uint8'));
0352 elseif ischar(Data)                  % TYPECAST cannot handle CHAR
0353    Engine.update(typecast(uint16(Data(:)), 'uint8'));
0354 elseif isa(Data, 'function_handle')
0355    Engine = CoreHash(ConvertFuncHandle(Data), Engine);
0356 else  % Most likely a user-defined object:
0357    try
0358       Engine = CoreHash(ConvertObject(Data), Engine);
0359    catch
0360       warning(['JSimon:', mfilename, ':BadDataType'], ...
0361          ['Type of variable not considered: ', class(Data)]);
0362    end
0363 end
0364 
0365 % return;
0366 
0367 % ******************************************************************************
0368 function FuncKey = ConvertFuncHandle(FuncH)
0369 %   The subfunction ConvertFuncHandle converts function_handles to a struct
0370 %   using the Matlab function FUNCTIONS. The output of this function changes
0371 %   with the Matlab version, such that DataHash(@sin) replies different hashes
0372 %   under Matlab 6.5 and 2009a.
0373 %   An alternative is using the function name and name of the file for
0374 %   function_handles, but this is not unique for nested or anonymous functions.
0375 %   If the MATLABROOT is removed from the file's path, at least the hash of
0376 %   Matlab's toolbox functions is (usually!) not influenced by the version.
0377 %   Finally I'm in doubt if there is a unique method to hash function handles.
0378 %   Please adjust the subfunction ConvertFuncHandles to your needs.
0379 
0380 % The Matlab version influences the conversion by FUNCTIONS:
0381 % 1. The format of the struct replied FUNCTIONS is not fixed,
0382 % 2. The full paths of toolbox function e.g. for @mean differ.
0383 FuncKey = functions(FuncH);
0384 
0385 % don't try to go into entire workspace, this is asking for trouble
0386 if isfield(FuncKey, 'workspace')
0387     logtext(atmlab('ERR'), ['Warning: not considering workspace for ' ...
0388         'function %s.  Risk of non-unique hash!\n'], FuncKey.function);
0389     FuncKey = rmfield(FuncKey, 'workspace');
0390 end
0391 
0392 % ALTERNATIVE: Use name and path. The <matlabroot> part of the toolbox functions
0393 % is replaced such that the hash for @mean does not depend on the Matlab
0394 % version.
0395 
0396 % Drawbacks: Anonymous functions, nested functions...
0397 % funcStruct = functions(FuncH);
0398 % funcfile   = strrep(funcStruct.file, matlabroot, '<MATLAB>');
0399 % FuncKey    = uint8([funcStruct.function, ' ', funcfile]);
0400 
0401 % Finally I'm afraid there is no unique method to get a hash for a function
0402 % handle. Please adjust this conversion to your needs.
0403 
0404 % return;
0405 
0406 % ******************************************************************************
0407 function DataBin = ConvertObject(DataObj)
0408 % Convert a user-defined object to a binary stream. There cannot be a unique
0409 % solution, so this part is left for the user...
0410 
0411 % Perhaps a direct conversion is implemented:
0412 DataBin = uint8(DataObj);
0413 
0414 % Or perhaps this is better:
0415 % DataBin = struct(DataObj);
0416 
0417 % return;
0418 
0419 % ******************************************************************************
0420 function Out = fBase64_enc(In)
0421 % Encode numeric vector of UINT8 values to base64 string.
0422 
0423 Pool = [65:90, 97:122, 48:57, 43, 47];  % [0:9, a:z, A:Z, +, /]
0424 v8   = [128; 64; 32; 16; 8; 4; 2; 1];
0425 v6   = [32, 16, 8, 4, 2, 1];
0426 
0427 In  = reshape(In, 1, []);
0428 X   = rem(floor(In(ones(8, 1), :) ./ v8(:, ones(length(In), 1))), 2);
0429 Y   = reshape([X(:); zeros(6 - rem(numel(X), 6), 1)], 6, []);
0430 Out = char(Pool(1 + v6 * Y));
0431 
0432 % return;

Generated on Mon 15-Sep-2014 13:31:28 by m2html © 2005