HAVE_FEATURE Test for optional functionality / version info. TORF = HAVE_FEATURE(TAG) TORF = HAVE_FEATURE(TAG, TOGGLE) VER_STR = HAVE_FEATURE(TAG, 'vstr') VER_NUM = HAVE_FEATURE(TAG, 'vnum') DATE = HAVE_FEATURE(TAG, 'date') INFO = HAVE_FEATURE(TAG, 'all') HAVE_FEATURE(TAG, 'clear_cache') HAVE_FEATURE('all', 'clear_cache') Returns availability, version and release information for optional functionality. All information is cached, and the cached values returned on subsequent calls. If the functionality exists, an attempt is made to determine the release date and version number. The second argument defines which value is returned, as follows: <none> 1 = optional functionality is available, 0 = not available 'vstr' version number as a string (e.g. '3.11.4') 'vnum' version number as numeric value (e.g. 3.011004) 'date' release date as a string (e.g. '21-Sep-2020') 'all' struct with fields named 'av' (for 'availability'), 'vstr', 'vnum' and 'date', and values corresponding to the above, respectively. For functionality that is not available, all calls with a string-valued second argument will return an empty value. Alternatively, the optional functionality specified by TAG can be toggled OFF or ON by calling HAVE_FEATURE with a numeric second argument TOGGLE with one of the following values: 0 - turn OFF the optional functionality 1 - turn ON the optional functionality (if available) -1 - toggle the ON/OFF state of the optional functionality Finally, passing 'clear_cache' as the second argument will cause the cached information to be cleared for the specified TAG or, if the first argument is 'all', for all optional functionality. When calling with 'clear_cache' no return value is defined. For each valid value of TAG, there is a corresponding feature detection function named HAVE_FEATURE_<TAG>, where <TAG> is the TAG value for the feature in question. This makes HAVE_FEATURE modular and extensible. Each feature detection function takes no input values, but returns three outputs TORF - 1 = feature is available, 0 = feature is not available VSTR - version number as a string (e.g. '3.11.4') RDATE - release date as a string (e.g. '21-Sep-2020') TAG values for HAVE_FEATURE detection functions included in MP-Test: matlab - code is running under MATLAB, as opposed to Octave octave - code is running under GNU Octave, as opposed to MATLAB Examples: if have_feature('matlab') disp(['Running MATLAB version ', have_feature('matlab', 'vstr')]) else disp(['Running Octave version ', have_feature('octave', 'vstr')]) end See also HAVE_FEATURE_MATLAB, HAVE_FEATURE_OCTAVE
0001 function rv = have_feature(tag, rtype) 0002 %HAVE_FEATURE Test for optional functionality / version info. 0003 % TORF = HAVE_FEATURE(TAG) 0004 % TORF = HAVE_FEATURE(TAG, TOGGLE) 0005 % VER_STR = HAVE_FEATURE(TAG, 'vstr') 0006 % VER_NUM = HAVE_FEATURE(TAG, 'vnum') 0007 % DATE = HAVE_FEATURE(TAG, 'date') 0008 % INFO = HAVE_FEATURE(TAG, 'all') 0009 % HAVE_FEATURE(TAG, 'clear_cache') 0010 % HAVE_FEATURE('all', 'clear_cache') 0011 % 0012 % Returns availability, version and release information for optional 0013 % functionality. All information is cached, and the cached values 0014 % returned on subsequent calls. If the functionality exists, an attempt is 0015 % made to determine the release date and version number. The second 0016 % argument defines which value is returned, as follows: 0017 % <none> 1 = optional functionality is available, 0 = not available 0018 % 'vstr' version number as a string (e.g. '3.11.4') 0019 % 'vnum' version number as numeric value (e.g. 3.011004) 0020 % 'date' release date as a string (e.g. '21-Sep-2020') 0021 % 'all' struct with fields named 'av' (for 'availability'), 'vstr', 0022 % 'vnum' and 'date', and values corresponding to the above, 0023 % respectively. 0024 % 0025 % For functionality that is not available, all calls with a string-valued 0026 % second argument will return an empty value. 0027 % 0028 % Alternatively, the optional functionality specified by TAG can be toggled 0029 % OFF or ON by calling HAVE_FEATURE with a numeric second argument TOGGLE 0030 % with one of the following values: 0031 % 0 - turn OFF the optional functionality 0032 % 1 - turn ON the optional functionality (if available) 0033 % -1 - toggle the ON/OFF state of the optional functionality 0034 % 0035 % Finally, passing 'clear_cache' as the second argument will cause the 0036 % cached information to be cleared for the specified TAG or, if the first 0037 % argument is 'all', for all optional functionality. When calling with 0038 % 'clear_cache' no return value is defined. 0039 % 0040 % For each valid value of TAG, there is a corresponding feature detection 0041 % function named HAVE_FEATURE_<TAG>, where <TAG> is the TAG value for the 0042 % feature in question. This makes HAVE_FEATURE modular and extensible. 0043 % Each feature detection function takes no input values, but returns 0044 % three outputs 0045 % TORF - 1 = feature is available, 0 = feature is not available 0046 % VSTR - version number as a string (e.g. '3.11.4') 0047 % RDATE - release date as a string (e.g. '21-Sep-2020') 0048 % 0049 % TAG values for HAVE_FEATURE detection functions included in MP-Test: 0050 % matlab - code is running under MATLAB, as opposed to Octave 0051 % octave - code is running under GNU Octave, as opposed to MATLAB 0052 % 0053 % Examples: 0054 % if have_feature('matlab') 0055 % disp(['Running MATLAB version ', have_feature('matlab', 'vstr')]) 0056 % else 0057 % disp(['Running Octave version ', have_feature('octave', 'vstr')]) 0058 % end 0059 % 0060 % See also HAVE_FEATURE_MATLAB, HAVE_FEATURE_OCTAVE 0061 0062 % The following calling syntaxes are also implemented to set and get the 0063 % entire cache struct and are used during testing only. 0064 % CACHE = HAVE_FEATURE('all', 'get_cache') 0065 % HAVE_FEATURE(CACHE, 'set_cache') 0066 0067 % MP-Test 0068 % Copyright (c) 2004-2020, Power Systems Engineering Research Center (PSERC) 0069 % by Ray Zimmerman, PSERC Cornell 0070 % 0071 % This file is part of MP-Test. 0072 % Covered by the 3-clause BSD License (see LICENSE file for details). 0073 % See https://github.com/MATPOWER/mptest for more info. 0074 0075 persistent h_f_cache; 0076 0077 action = 'D'; %% detecting functionality (default) 0078 if nargin > 1 0079 if isnumeric(rtype) && ~isempty(rtype) 0080 action = 'T'; %% toggling functionality 0081 on_off = rtype; 0082 if on_off < 0 %% flip the toggle 0083 TorF = have_feature(tag); 0084 on_off = ~TorF; 0085 end 0086 elseif length(rtype) > 4 0087 switch lower(rtype) 0088 case 'get_cache' 0089 action = 'C'; %% getting cache 0090 rv = h_f_cache; 0091 case 'set_cache' 0092 action = 'C'; %% setting cache 0093 h_f_cache = tag; 0094 case 'clear_cache' 0095 action = 'C'; %% clearing cache 0096 if strcmpi(tag, 'all') %% delete all fields 0097 h_f_cache = struct(); 0098 else %% delete field to force single re-check 0099 if isfield(h_f_cache, tag) 0100 h_f_cache = rmfield(h_f_cache, tag); 0101 end 0102 end 0103 end 0104 end 0105 end 0106 0107 if action == 'T' %% change availability 0108 if on_off %% turn on if available 0109 if isfield(h_f_cache, tag) %% delete field to force single re-check 0110 h_f_cache = rmfield(h_f_cache, tag); 0111 end 0112 else %% turn off 0113 if ~isfield(h_f_cache, tag) %% not yet been checked 0114 TorF = have_feature(tag); %% cache result first 0115 end 0116 h_f_cache.(tag).av = 0; %% then turn off 0117 end 0118 TorF = have_feature(tag); %% return availability 0119 %% (recheck if ON, cached 0 if OFF) 0120 elseif action == 'D' %% detect availability 0121 %% info not yet cached? 0122 if ~isfield(h_f_cache, tag) 0123 %%----- determine installation status, version number, etc. ----- 0124 %% initialize default values 0125 TorF = 0; 0126 vstr = ''; 0127 rdate = ''; 0128 0129 %% check for feature 0130 fcn = ['have_feature_' tag]; 0131 if isempty(which(fcn)) 0132 warning('have_feature: unknown functionality ''%s''', tag); 0133 vstr = 'unknown'; 0134 else 0135 [TorF, vstr, rdate] = feval(fcn); 0136 end 0137 0138 %% assign values to cache 0139 h_f_cache.(tag).av = TorF; 0140 h_f_cache.(tag).vstr = vstr; 0141 if isempty(vstr) 0142 h_f_cache.(tag).vnum = []; 0143 else 0144 h_f_cache.(tag).vnum = vstr2num(vstr); 0145 end 0146 h_f_cache.(tag).date = rdate; 0147 end 0148 end 0149 0150 %% extract desired values from cache 0151 if action ~= 'C' || nargout 0152 if nargin < 2 || action == 'T' 0153 rv = h_f_cache.(tag).av; 0154 else 0155 switch lower(rtype) 0156 case 'vstr' 0157 rv = h_f_cache.(tag).vstr; 0158 case 'vnum' 0159 rv = h_f_cache.(tag).vnum; 0160 case 'date' 0161 rv = h_f_cache.(tag).date; 0162 case 'all' 0163 rv = h_f_cache.(tag); 0164 case {'', 'av'} 0165 rv = h_f_cache.(tag).av; 0166 end 0167 end 0168 end 0169 0170 function num = vstr2num(vstr) 0171 % Converts version string to numerical value suitable for < or > comparisons 0172 % E.g. '3.11.4' --> 3.011004 0173 pat = '\.?(\d+)'; 0174 [s,e,tE,m,t] = regexp(vstr, pat); 0175 b = 1; 0176 num = 0; 0177 for k = 1:length(t) 0178 num = num + b * str2num(t{k}{1}); 0179 b = b / 1000; 0180 end