/usr/share/psychtoolbox-3/PsychFiles/Var2Str.m is in psychtoolbox-3-common 3.0.14.20170103+git6-g605ff5c.dfsg1-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 | function str = Var2Str(varargin)
% str = Var2Str(in,name)
%
% Takes variable IN and creates a string representation of it that would
% return the original variable when fed to eval(). NAME is the name of the variable
% that will be printed in this string.
% Can process any (combination of) MATLAB built-in datatype
%
% examples:
% Var2Str({4,7,'test',@exp})
% ans =
% {4,7,'test',@exp}
%
% var.field1.field2 = {logical(1),'yar',int32(43),[3 6 1 2],@isempty};
% Var2Str(var,'var2')
% ans =
% var2.field1.field2 = {true,'yar',int32(43),[3,6,1,2],@isempty};
% DN 2008-01 Wrote it.
% DN 2008-07-30 Added support for function handles
% DN 2008-07-31 Added checking of MATLAB version where needed
% DN 2008-08-06 Lessened number of output lines needed to represent
% variable in some cases
% DN 2008-08-12 Added wronginputhandler() for easy creation of specific
% error messages on wrong input + added sparse support
% DN 2011-06-07 Simple variables while having only one input argument
% didn't actually work....
% DN 2011-06-08 reworked 2D+ engine and added a dispatcher to remove code
% duplication. Also put addition of LHS to expression in one
% common place.
% DN 2011-06-09 Added handling of empty and/or fieldless structs
% TODO: make extensible by userdefined object parser for user specified
% datatypes - this will make this function complete
% make string of values in input, output is a cell per entry
strc = dispatcher(varargin{:});
if iscell(strc)
% align equals-signs (autistic)
indices = strfind(strc,'=');
indices = cellfun(@(x)x(1),indices);
MaxIndex = max(indices);
for p = 1:length(strc)
i = indices(p);
dif = MaxIndex - i;
strc{p} = [strc{p}(1:i-1) repmat(' ',1,dif) strc{p}(i:end)];
end
% make string out of the stringcells
str = [strc{:}];
else
str = strc;
end
% dispatch string representation creation of datatype to handler for that
% datatype
function str = dispatcher(varargin)
if isnumeric(varargin{1}) || islogical(varargin{1})
str = numeric2str(varargin{:});
elseif ischar(varargin{1})
str = str2str(varargin{:});
elseif iscell(varargin{1})
str = cell2str(varargin{:});
elseif isstruct(varargin{1})
str = struct2str(varargin{:});
elseif isa(varargin{1},'function_handle')
str = funchand2str(varargin{1});
else
wronginputhandler(varargin{:});
end
% add LHS if needed
if ischar(str)
if nargin==2
str = {[varargin{2} ' = ' str ';' char(10)]};
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% functions to deal with the different datatypes
% this function handles the unsupported data types
function wronginputhandler(input,name)
if nargin == 1
at = '';
else
at = [char(10) 'Error at ' name];
end
switch class(input)
case 'inline'
error('Inline functions not supported, they are deprecated.\nPlease see ''help function_handle'' for information on an alternative.%s',at)
otherwise
error('input of type %s is not supported.%s',class(input),at)
end
% this function handles numerical and logical data types
function str = numeric2str(input,name)
psychassert(isnumeric(input)||islogical(input),'numeric2str: Input must be numerical or logical, not %s',class(input))
if numel(input)>4 && isscalar(unique(input))
% special case, all same value
str = constant2str(input);
elseif isempty(input) || ndims(input)<=2
if ismember(class(input),{'double','logical'})
str = mat2str(input,17);
else
% for any non-double datatype, preserve type - double is default
str = mat2str(input,17,'class');
end
str = regexprep(str,'\s+',' ');
% check for "Infi" which is an infinity imaginary component.
% to recreate that, we need to replace it with: complex(0, inf)
str = strrep(str,'Infi','complex(0, inf)');
else
psychassert(nargin==2,'input argument name must be defined if processing 2D+ matrix');
str = mat2strhd(input,name);
end
% this function handles the char data type -> strings
function str = str2str(input,name)
psychassert(ischar(input),'str2str: Input must be char, not %s',class(input))
if numel(input)>4 && isscalar(unique(input))
% special case, all same value
str = constant2str(input);
elseif isempty(input) || ndims(input)<=2
str = mat2str(input,17);
else
psychassert(nargin==2,'input argument name must be defined if processing 2D+ string matrix');
str = mat2strhd(input,name);
end
% this one for cells
function str = cell2str(input,name)
psychassert(iscell(input),'cell2str: Input must be cell, not %s',class(input));
qstruct = IsACell(input,@isstruct); % recursively check if there is any struct in the cell
q2dplus = IsACell(input,@(x)ndims(x)>2); % recursively check if there is any element in the cell extending over more than 2 dimensions
if isempty(input)
if ndims(input)==2 && all(size(input)==0)
str = '{}';
else
s = size(input);
str = ['cell(' regexprep(mat2str(s,17),'\s+',',') ')'];
end
elseif ~qstruct && ~q2dplus
[nrow ncol] = size(input);
str = '{';
% process cell per element
for p = 1:nrow
for q=1:ncol
if isstruct(input{p,q})
error('structs should not be processed here in any circumstance');
else
str = [str dispatcher(input{p,q})];
end
if q~=ncol
str = [str ','];
end
end
if p~=nrow
str = [str ';'];
end
end
str = [str '}'];
else
psychassert(nargin==2,'input argument name must be defined if processing 2D+ cell or cell containing structs');
str = cell2strhd(input,name);
end
% and this one for structs
function strc = struct2str(input,name)
if ~isstruct(input)
error('Input is not struct')
end
%%%%%
fields = fieldnames(input);
strc = [];
if isempty(fields)
% handle case of no fields
strc = 'struct()';
if ~isscalar(input)
sizestr = regexprep(mat2str(size(input),17),'\s+',' ');
strc = ['repmat(' strc ',' sizestr ')'];
end
elseif all(arrayfun(@(x) all(structfun(@(y) ndims(y)==2 && all(size(y)==0) && isa(y,'double'),x)),input))
% handle case of all fields default-empty (0x0 double)
nf = length(fields);
fields = MergeCell('''',fields,''',[]');
strc = cell2mat(['struct(' Interleave(fields,repmat(',',1,nf-1)) ')']);
if ~isscalar(input)
sizestr = regexprep(mat2str(size(input),17),'\s+',' ');
strc = ['repmat(' strc ',' sizestr ')'];
end
else
% struct has actual data, process
psychassert(nargin==2,'input argument name must be defined if processing a struct');
if isscalar(input)
fields = fieldnames(input);
for r=1:length(fields)
wvar = input.(fields{r});
namesuff = ['.' fields{r}];
strc = [strc; dispatcher(wvar,[name namesuff])];
end
else
strc = struct2strnonscalar(input,name);
end
end
function str = funchand2str(input)
psychassert(isa(input,'function_handle'),'funchand2str: Input must be a function handle, not %s',class(input));
str = func2str(input);
if str(1)~='@'
str = ['@' str];
end
%%%% function for special case of constant array
function str = constant2str(in)
item = unique(in);
s = size(in);
sizestr = regexprep(mat2str(s,17),'\s+',' ');
itemstr = dispatcher(item);
if islogical(item)
str = [itemstr '(' strrep(sizestr(2:end-1),' ',',') ')'];
else
str = ['repmat(' itemstr ',' sizestr ')'];
end
return;
%%%% HD functions for variables of more than 2 non-singleton dimensions
function strc = mat2strhd(in,name)
s = size(in);
% unwrap all higher dimensions into a 2D mat, e.g., make a 4x2x3 into a
% 12x2 where every four rows contain one element from the third dimension
in=permute(in,[1,3:numel(s),2]);
in=reshape(in,[],s(2));
% wrap in cell per higher-dimension element
in=num2cellStrided(in,[s(1:2)]);
% prepare output indices
idxs = size2idxs(s,2);
fmt = [name '(:,:' repmat(',%d',[1,length(s)-2]) ')'];
% dispatch each 2D to correct interpreter
strc = cellfun(@(x,y) dispatcher(x,[name sprintf(fmt,y)]),in,num2cell(idxs,2));
function strc = cell2strhd(in,name)
strc = [];
siz = size(in);
qDontProcess = cellfun(@(x) ndims(x)==2 && all(size(x)==0) && isa(x,'double'),in);
for p=1:numel(in)
if qDontProcess(p)
continue;
end
[idx{1:numel(siz)}] = ind2sub(siz,p);
namesuff = ['{' Interleave([idx{:}],repmat(',',1,length(idx)-1)) '}'];
strc = [strc; dispatcher(in{p},[name namesuff])];
end
function strc = struct2strnonscalar(in,name)
strc = [];
siz = size(in);
qDontProcess = arrayfun(@(x) all(structfun(@(y) ndims(y)==2 && all(size(y)==0) && isa(y,'double'),x)),in);
for p=1:numel(in)
if qDontProcess(p)
continue;
end
[idx{1:numel(siz)}] = ind2sub(siz,p);
namesuff = ['(' Interleave([idx{:}],repmat(',',1,length(idx)-1)) ')'];
strc = [strc; struct2str(in(p),[name namesuff])];
end
%%% other helpers
function res = size2idxs(siz,noff)
if nargin==1
noff = 0;
end
narg=numel(siz);
n=narg-noff;
if n
arg=cell(n,1);
x=cell(n,1);
for i=1:n
arg{i}=1:siz(i+noff);
end
else
res = [];
return;
end
if n > 1
[x{1:n,1}]=ndgrid(arg{1:end});
res=reshape(cat(n+1,x{:}),[],n);
else
res=arg{:}.';
end
function res = num2cellStrided(in,stride)
% the function is only tested 2D for now, don't want to think about higher
% dims, but it might just work equally fine
siz = size(in);
ndim = numel(siz);
ncell = siz./stride;
assert(~any(mod(ncell,1)),'size needs to be a multiple of stride for each dimension');
res = reshape( in , Interleave(stride,ncell) );
res = permute( res, InterLeave(1:ndim,ndim+1:ndim*2) );
res = squeeze(num2cell(res,[1:ndim]));
|