MatrixBerryCore
parseparext.m
Go to the documentation of this file.
1 function [reg,isRegSpecVec,varargout]=parseparext(args,propNameValMat,varargin)
2 import mxberry.core.check.*;
3 import mxberry.core.checkvar;
4 import mxberry.core.ismembercellstr;
5 import mxberry.core.throwerror;
6 %
7 if ~isempty(propNameValMat)
8  if ~(ischar(propNameValMat)&&lib.isrow(propNameValMat)||...
9  iscell(propNameValMat)&&ismatrix(propNameValMat)&&...
10  (size(propNameValMat,1)==1||size(propNameValMat,1)==2||...
11  size(propNameValMat,1)==3&&...
12  lib.iscellofstrorfunc(propNameValMat(3,:))&&...
13  iscellstr(propNameValMat(1,:))))
14  throwerror('wrongInput',...
15  'propNameValMat is badly formed');
16  end
17  %
18  propNameList=propNameValMat(1,:);
19  if ischar(propNameList)
20  propNameList={lower(propNameList)};
21  else
22  propNameList=lower(propNameList);
23  end
24  %
25  isDefSpec=size(propNameValMat,1)>1;
26  isCheckSpec=size(propNameValMat,1)>2;
27  isPropNameSpec=true;
28 else
29  isPropNameSpec=false;
30  isDefSpec=false;
31  propNameList=propNameValMat;
32  isCheckSpec=false;
33 end
34 [inpReg,inpProp]=mxberry.core.parseparams(varargin,...
35  {'regCheckList','regDefList','propRetMode','isObligatoryPropVec',...
36  'isDefaultPropSpecVec'});
37 %
38 if ~isempty(inpReg)&&~isempty(inpReg{1})
39  isNRegExpSpec=true;
40  nRegExpVec=inpReg{1};
41  if numel(nRegExpVec)==1
42  nRegExpVec=[nRegExpVec,nRegExpVec];
43  end
44 else
45  isNRegExpSpec=false;
46  nRegExpVec=[0,Inf];
47 end
48 [reg,prop]=mxberry.core.parseparams(args,propNameList,inpReg{:});
49 %
50 nRegs=length(reg);
51 isRegDefListSpec=false;
52 isPropRetModeSpec=false;
53 isObligatoryPropVecSpec=false;
54 isDefPropIndicatorSpec=false;
55 if ~isempty(inpProp)
56  nInpProps=length(inpProp);
57  for iInpProp=1:2:nInpProps-1
58  switch lower(inpProp{iInpProp})
59  case 'regchecklist'
60  regCheckList=inpProp{iInpProp+1};
61  checkvar(regCheckList,...
62  @(x)iscell(x)&&lib.isrow(x)&&...
63  (~isNRegExpSpec&&numel(x)>=nRegs||...
64  isNRegExpSpec&&numel(x)<=nRegExpVec(2)));
65  %
66  for iReg=1:nRegs
67  checkgen(reg{iReg},regCheckList{iReg},...
68  sprintf('regular arg #%d',iReg),'nCallerStackStepsUp',2);
69  end
70  case 'regdeflist'
71  regDefList=inpProp{iInpProp+1};
72  checkgen(regDefList,...
73  @(x)iscell(x)&&lib.isrow(x)&&...
74  (isNRegExpSpec&&...
75  numel(x)<=nRegExpVec(2)&&...
76  numel(x)>=nRegExpVec(1)||~isNRegExpSpec));
77  isRegDefListSpec=true;
78  case 'propretmode'
79  propRetMode=inpProp{iInpProp+1};
80  checkgen(propRetMode,...
81  @(x)lib.isstring(x)&&any(strcmpi(x,{'list','separate'})));
82  propRetMode=lower(propRetMode);
83  isPropRetModeSpec=true;
84  case 'isobligatorypropvec'
85  isObligatoryPropVec=inpProp{iInpProp+1};
86  checkgen(isObligatoryPropVec,'islogical(x)&&isrow(x)');
87  if ~isPropNameSpec
88  throwerror('wrongInput',...
89  ['isObligatoryPropVec property is allowed only ',...
90  'when property names are specified']);
91  end
92  isObligatoryPropVecSpec=true;
93  %
94  case 'isdefaultpropspecvec'
95  isDefaultPropSpecVec=inpProp{iInpProp+1};
96  checkgen(isDefaultPropSpecVec,'islogical(x)&&isrow(x)');
97  if ~isDefSpec
98  throwerror('wrongInput:defPropSpecVecNoDefValues',...
99  ['isDefaultPropSpecVec property is allowed only ',...
100  'when default property values are specified']);
101  end
102  isDefPropIndicatorSpec=true;
103  otherwise
104  throwerror('wrongInput','Oops, we shouldn''t be here');
105  end
106  end
107 end
108 if ~isPropRetModeSpec
109  if isPropNameSpec
110  propRetMode='separate';
111  else
112  propRetMode='list';
113  end
114 end
115 if isDefPropIndicatorSpec&&strcmp(propRetMode,'separate')
116  throwerror('wrongInput:defPropSpecVecNotInListMode',...
117  'isDefaultPropSpecVec is not supported when propRetMode=separate');
118 
119 end
120 if ~isPropNameSpec&&strcmp(propRetMode,'separate')
121  throwerror('wrongInput',...
122  'propRetMode=separate is not supported for empty propNameValMat');
123 end
124 %
125 if isRegDefListSpec
126  nRegDefs=length(regDefList);
127  if nRegDefs>nRegs
128  reg=[reg,cell(1,nRegDefs-nRegs)];
129  isRegSpecVec=[true(1,nRegs),false(1,nRegDefs-nRegs)];
130  for indArg=nRegs+1:nRegDefs
131  reg{indArg}=regDefList{indArg};
132  end
133  else
134  isRegSpecVec=true(1,nRegs);
135  end
136 else
137  isRegSpecVec=true(1,nRegs);
138 end
139 %
140 nElems=length(prop);
141 propResNameList=lower(prop(1:2:nElems-1));
142 propResValList=prop(2:2:nElems);
143 [isUnique,propUResNameList]=mxberry.core.isunique(propResNameList);
144 if ~isUnique
145  nResProps=nElems*0.5;
146  [~,indThereVec]=ismember(propResNameList,propUResNameList);
147  nResPropSpecVec=accumarray(indThereVec.',ones(nResProps,1));
148  isPropDupVec=nResPropSpecVec>1;
149  dupPropListStr=mxberry.core.cell.cellstr2expression(...
150  propUResNameList(isPropDupVec));
151  throwerror('wrongInput:duplicatePropertiesSpec',...
152  sprintf('properties %s are specified more than once',...
153  dupPropListStr));
154 end
155 %
156 if isPropNameSpec
157  [isPropSpecVec,indLocVec]=ismembercellstr(propNameList,propResNameList);
158  propValList=cell(size(propNameList));
159  propValList(isPropSpecVec)=propResValList(indLocVec(isPropSpecVec));
160  if isDefSpec
161  propValList(~isPropSpecVec)=propNameValMat(2,~isPropSpecVec);
162  end
163  if isCheckSpec&&any(isPropSpecVec)
164  cellfun(@(x,y,z)checkgen(x,y,z,'nCallerStackStepsUp',2),...
165  propValList(isPropSpecVec),...
166  propNameValMat(3,isPropSpecVec),...
167  strcat('property:',propNameList(isPropSpecVec)));
168  end
169  nProps=length(propNameList);
170 else
171  isPropSpecVec=true(size(propResNameList));
172  propValList=propResValList;
173  nProps=length(propResValList);
174 end
175 if isObligatoryPropVecSpec
176  isObligAndNotSpecVec=~isPropSpecVec&isObligatoryPropVec;
177  if any(isObligAndNotSpecVec)
178  throwerror('wrongInput',['property(es) %s are obligatory but ',...
179  'were not specified'],...
180  mxberry.core.cell.cell2tablestr([],...
181  propNameList(isObligAndNotSpecVec),','));
182  end
183 end
184 %
185 nOut=nargout-2;
186 switch propRetMode
187  case 'list'
188  if nOut>2
189  throwerror('wrongInput',...
190  ['retPropAsList=true so number of ',...
191  'output arguments cannot exceed 4']);
192  end
193  if nOut>0
194  if isPropNameSpec
195  if isDefPropIndicatorSpec
196  isPropFilledVec=isPropSpecVec|...
197  isDefSpec&isDefaultPropSpecVec;
198  else
199  isPropFilledVec=isPropSpecVec|...
200  isDefSpec;
201  end
202  %
203  prop=[propNameList(isPropFilledVec);...
204  propValList(isPropFilledVec)];
205  varargout{1}=transpose(prop(:));
206  else
207  varargout{1}=prop;
208  end
209  if nOut>1
210  varargout{2}=isPropSpecVec;
211  end
212  end
213  case 'separate'
214  if nOut>2*nProps
215  throwerror('wrongInput',...
216  'number of output arguments cannot exceed 2+ 2*nProperties');
217  end
218  %
219  varargout(1:min(nOut,nProps))=propValList(1:min(nOut,nProps));
220  if nOut>nProps
221  varargout((nProps+1):min(nOut,2*nProps))=...
222  num2cell(isPropSpecVec(1:min(nOut-nProps,nProps)));
223  end
224  otherwise
225  throwerror('wrongInput',...
226  'Oops, we shouldn''t be here');
227 end
function throwerror(in msgTag, in varargin)
THROWERROR works similarly to built-in ERROR function in case when there is no output arguments but s...
function parseparext(in args, in propNameValMat, in varargin)
PARSEPAREXT behaves in the same way as mxberry.core.parseparams but returns property values in a more...
function checkvar(in x, in typeSpec, in varargin)
CHECKVAR checks a generic condition provided by typeSpec string in the following format: &#39;isnumeric(x...
function checkgen(in x, in typeSpec, in varargin)
CHECKGEN checks a generic condition provided by typeSpec string in the following format: &#39;isnumeric(x...
function ismember(in leftVec, in rightVec, in varargin)
ISMEMBER - ismember implementation for arrays of any type.