📄 read_structure.m
字号:
function resp = read_structure(st,args)
% READ Read values stored in the location pointed to the STRUCTURE object ST.
%
% O = READ(st) - reads the numeric values of each STRUCTURE member in ST. This returns a Matlab
% structure having the member names as fields.
%
% O = READ(st,val,member) - reads the numeric value of the STRUCTURE member specified by MEMBER.
%
% O = READ(st,val,member,varargin) - reads the numeric value of the STRUCTURE member specified by MEMBER,
% where VARARGIN are extra READ options. See READ options of MEMBER.
%
% O = READ(st,index,val,member) - reads the numeric value of the member of the STRUCTURE element INDEX.
%
% O = READ(st,index,val,member,varargin) - reads the numeric value of the member of the STRUCTURE
% element INDEX, where VARARGIN are extra READ options. See READ options of MEMBER.
%
% The output O is not in Matlab structure format when reading a particular member value.
%
% Copyright 2002 The MathWorks, Inc.
error(nargchk(2,2,nargin));
if ~ishandle(st),
error('First parameter must be a STRUCTURE handle ');
end
index = [1:prod(st.size)];
membidx = [1:length(st.membname)];
nargs = length(args) + 1;
if nargs==1 | (nargs==2 & isempty(args{1})),
next = 1;
all_index = 1;
descr = 'structure';
% Create an array of structures
emptySt = struct([]);
emptySt(prod(st.size)).('dummy') = [];
if length(st.size)==1, emptySt = reshape(emptySt,1,st.size);
else emptySt = reshape(emptySt,st.size);
end
SendWarning(st,{'largestruct','mangle'});
elseif nargs>=2,
% If 2nd argument is index, READ(st,1,...) or READ(st,1,'memb',...)
if isnumeric(args{1}) & ~isempty(args{1}),
index = round(args{1});
if any(index<=0) | any(index>st.size)
error(['Invalid STRUCTURE index: ' num2str(args{1})] );
end
if length(args)==1, % read one index only
next = 1;
all_index = 0;
descr = 'indexed_structure';
emptySt = CreateEmptyStruct(st);
resp = emptySt;
SendWarning(st,{'mangle'});
else
next = 2;
if nargs>2
membidx = strmatch(args{2},st.membname,'exact');
next = 3;
end
all_index = 0;
descr = 'indexed_member';
end
% If 2nd argument is struct member, READ(st,'memb',...)
elseif isempty(args{1}) | (ischar(args{1}) & strmatch(args{1},st.membname,'exact')),
if isempty(args{1})
args = {args{2}};
end
membidx = strmatch(args{1},st.membname,'exact');
next = 2;
all_index = 1;
descr = 'all_members';
resp = CreateArrayForAllElementOutput(st,membidx);
else
error('Invalid input: Second input must be a STRUCTURE index or member name');
end
end
stOrigAddr = st.address; % original address of object
membobjlist = cell(1,membidx(end)); % create a cell array of member objects - index corresponds to member order (1-based)
for i=membidx, membobjlist{i} = my_getmember(st,i); end
memboffset = st.member.containerobj_memboffset; % get all member offsets
i=1;
if strcmp(descr,'structure'), % separate loop - for faster read operation
warning off backtrace;
for idx=index,
temp = struct([]);
for memid=membidx,
% sname = st.member.containerobj_membname{memid};
sname = st.member.containerobj_mangledmembname{memid};
% adjust member address
membtemp = membobjlist{memid};
membtemp.address = [stOrigAddr(1)+memboffset(memid)+st.storageunitspervalue*(idx-1), membtemp.address(2)];
% call regular READ on each member
temp(1).(sname) = read(membtemp);
end
resp(i) = temp;
i = i+1;
end
warning on backtrace;
else
% Compute linear memory index from index and array-order info
if strcmp(descr,'indexed_structure') | strcmp(descr,'indexed_member'),
index = ComputeLinearIndex(st,index);
end
warning off backtrace;
for idx=index,
temp = struct([]);
for memid=membidx,
% sname = st.member.containerobj_membname{memid};
sname = st.member.containerobj_mangledmembname{memid};
% adjust member address
membtemp = membobjlist{memid};
membtemp.address = [stOrigAddr(1)+memboffset(memid)+st.storageunitspervalue*(idx-1), membtemp.address(2)];
% call regular READ on each member
if strcmp(descr,'indexed_structure') | isempty([args{next:end}]), % or 'structure'
temp(1).(sname) = read(membtemp);
else
% extra arguments
num_extra_args = length(args{next:end});
if num_extra_args==1
temp(1).(sname) = read(membtemp,args{next});
elseif num_extra_args==2
temp(1).(sname) = read(membtemp,args{next},args{next+1});
else
eval(call_arbitrary_args(num_extra_args));
end
end
end
if strcmp(descr,'indexed_structure')
resp = temp;
elseif strcmp(descr,'indexed_member')
resp = temp.(sname);
elseif strcmp(descr,'all_members')
if iscell(resp), resp{i} = temp.(sname);
else resp(i) = temp.(sname);
end
end
i = i+1;
end
warning on;
warning on backtrace;
end
% Rearrange output data according to array-order property
if strcmp(descr,'all_members') | strcmp(descr,'structure')
if length(st.size) > 1, % Non-indexed, arrange according to 'arrayorder' prop
if strcmp(st.arrayorder,'row-major'),
resp = resp( GetMatlabIndex(st) );
end
resp = reshape(resp,st.size);
end
end
ReturnOrignalMemberAddress(st,membidx,stOrigAddr);
%-------------------------------------------
function str = call_arbitrary_args(num_args)
str = 'temp(1).(sname) = read(membtemp,args{next},args{next+1},';
for i=2:num_args-1
str = horzcat(str,['args{next+' num2str(i) '},']);
end
str(end) = ')';
str = horzcat(str,';');
%-------------------------------------------
function emptySt = CreateEmptyStruct(st)
emptySt = struct([]);
for memb=st.membname
m_memb = p_manglename(st,memb{1},'off');
emptySt(1).(m_memb) = [];
end
%-------------------------------------------
function emptySt = CreateEmptyStructFromInfo(m_info)
emptySt = struct([]);
m_names = fieldnames(m_info);
for i = 1:length(m_names)
memb = m_names{i};
emptySt(1).(memb) = [];
end
%------------------------------------------
function resp = CreateArrayForAllElementOutput(st,membidx)
membinfo = st.member.containerobj_membinfo;
% m_membname = st.member.containerobj_mangledmembname{membidx};
minfo_membname = fieldnames(membinfo)';
minfo_membname = minfo_membname{membidx};
membtype = membinfo.(minfo_membname).type;
isscalar = length(st.size)==1;
if strcmp(membtype,'char') | strfind(membtype,'enum ')
if isscalar, resp = cell(1,st.size);
else resp = cell(st.size);
end
elseif strfind(membtype,'struct ') | strfind(membtype,'union ')
% emptySt = CreateEmptyStructFromInfo(membinfo.(m_membname).members);
emptySt = struct('dummy',[]);
emptySt(prod(st.size)).('dummy') = [];
if isscalar, resp = reshape(emptySt,1,st.size);
else resp = repmat(emptySt,st.size);
end
else
if isscalar, resp = zeros(1,st.size);
else resp = zeros(st.size);
end
end
%--------------------------------------------
function dummy = ReturnOrignalMemberAddress(st,membidx,baseAddr)
for membid = membidx
obj = st.member.(st.member.containerobj_mangledmembname{membid});
origAddr = [baseAddr(1)+st.member.containerobj_memboffset(membid),baseAddr(2)];
set(obj,'address',origAddr);
end
%--------------------------------------------
function resp = my_getmember1(str,membid,structidx)
resp = str.member.(str.member.containerobj_mangledmembname{membid});
resp.address = [resp.address(1)+str.storageunitspervalue*(structidx-1), resp.address(2)];
%--------------------------------------------
function resp = my_getmember(str,membid)
resp = str.member.(str.member.containerobj_mangledmembname{membid});
%--------------------------------------------
function linearindex = getLinearIndex(str,subs)
try
index_shaped = round(reshape(subs,length(str.size),[])');
catch
error(['Index Array must be an (N x ' num2str(length(st.size)) ') array of indices' ]);
end
for subscript = index_shaped',
if any(subscript < 1) | any(subscript' > str.size),
error(['INDEX has an entry: [' num2str(subscript') '], which exceeds the defined size of object ']);
end
end
addrange = index2addr(str,index_shaped);
uidata = read_memoryobj(str,addrange',dtimeout);
uidata = reshape(uidata,str.storageunitspervalue,[]);
nvalues = size(uidata);
nvalues = nvalues(2);
%-----------------------------------------
function linearindex = GetMatlabIndex(nn)
nsize = nn.size;
subsc = [];
totalnumel = prod(nsize);
len = length(nsize);
subsc = p_ind2sub(nn,nsize,[1:totalnumel],'col-major'); % index in a) C if row-major b) Matlab if col-major
linearindex = p_sub2ind(nn,nsize,subsc,'row-major'); % map indices to native Matlab array order
if ~isequal(unique(linearindex),sort(linearindex))
error('Error generating linear index. Please report this error to MathWorks.');
end
%-----------------------------------------
function linearindex = ComputeLinearIndex(nn,index)
if ~isequal(length(index),length(nn.size)) & length(index)
error(['Index must be a (1 x ' num2str(length(nn.size)) ') array ' ]);
end
if length(nn.size)>1,
linearindex = p_sub2ind(nn,nn.size,index,nn.arrayorder);
else
linearindex = index;
end
%----------------------------------------------
function SendWarning(st,warnlist)
warning on; warning off backtrace;
for i=1:length(warnlist),
switch warnlist{i}
case 'largestruct'
if prod(st.size)*(st.storageunitspervalue)>150,
warning('You are reading a large structure, this may take a while... ');
end
case 'mangle'
if ~isequal(st.membname,st.member.containerobj_mangledmembname),
warning('One or more member names on the result has been renamed to become a valid MATLAB structure fieldname ');
end
otherwise
end
end
warning on backtrace;
% [EOF] read_structure.m
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -