function results=parseresultsfromdisk(filename,iosplit)
%PARSERESULTSFROMDISK - ...
%
%   Usage:
%      results=parseresultsfromdisk(filename,iosplit)

if iosplit,
	results=parseresultsfromdiskiosplit(filename);
else
	results=parseresultsfromdiskioserial(filename);
end

%process patch if necessary
results=MatlabProcessPatch(results);

function results=parseresultsfromdiskioserial(filename) % {{{
%PARSERESULTSFROMDISK - ...
%
%   Usage:
%      results=parseresultsfromdiskioserial(filename)

%Open file
fid=fopen(filename,'rb');
if(fid==-1),
	error(['loadresultsfromdisk error message: could not open ',filename,' for binary reading']);
end
results=struct();

%Read fields until the end of the file.
result=ReadData(fid);
while ~isempty(result), 
	%Get time and step
	results(result.step).step=result.step;
	results(result.step).time=result.time; 

	%Add result
	if (length(results)>=result.step & isfield(results,result.fieldname) & ~strcmp(result.fieldname,'SolutionType')),
			results(result.step).(result.fieldname)=[ results(result.step).(result.fieldname); result.field];
	else
		results(result.step).(result.fieldname)=result.field;
	end

	%read next result
	result=ReadData(fid);

end

fclose(fid);
% }}}
function results=parseresultsfromdiskiosplit(filename) % {{{
%PARSERESULTSFROMDISKIOSPLIT - ...
%
%   Usage:
%      results=parseresultsfromdiskiosplit(filename)

%Open file
fid=fopen(filename,'rb');
if(fid==-1),
	error(['loadresultsfromdisk error message: could not open ',filename,' for binary reading']);
end
results=struct();

%if we have done split I/O, ie, we have results that are fragmented across patches, 
%do a first pass, and figure out the structure of results
result=ReadDataDimensions(fid);
while ~isempty(result),

	%Get time and step
	results(result.step).step=result.step;
	results(result.step).time=result.time; 

	%Add result
	if strcmpi(result.fieldname,'Patch'),
		results(result.step).(result.fieldname)=[0 result.N];
	else
		results(result.step).(result.fieldname)=NaN;
	end

	%read next result
	result=ReadDataDimensions(fid);
end

%do a second pass, and figure out the size of the patches
fseek(fid,0,-1); %rewind
result=ReadDataDimensions(fid);
while ~isempty(result),

	%Add result
	if strcmpi(result.fieldname,'Patch'),
		patchdimensions=results(result.step).(result.fieldname);
		results(result.step).(result.fieldname)=[patchdimensions(1)+result.M result.N];
	end

	%read next result
	result=ReadDataDimensions(fid);
end

%allocate patches
for i=1:length(results),
	results(i).Patch=zeros(results(i).Patch(1),results(i).Patch(2));
	results(i).counter=1; %use to index into the patch
end

%third pass, this time to read the real information
fseek(fid,0,-1); %rewind
result=ReadData(fid);
while ~isempty(result),

	%Get time and step
	results(result.step).step=result.step;
	results(result.step).time=result.time; 

	%Add result
	if strcmpi(result.fieldname,'Patch'),
		counter=results(result.step).counter;
		counter2=counter+size(result.field,1)-1;
		results(result.step).(result.fieldname)(counter:counter2,:)=result.field;

		%increment counter: 
		results(result.step).counter=counter2+1;
	else
		results(result.step).(result.fieldname)=result.field;
	end

	%read next result
	result=ReadData(fid);

end

%close file
fclose(fid);
	% }}}
function result=ReadData(fid) % {{{
%READDATA - ...
%
%   Usage:
%      field=ReadData(fid)

%read field
[length,count]=fread(fid,1,'int');

if count==0,
	result=struct([]);
else
	fieldname=fread(fid,length,'char');
	fieldname=fieldname(1:end-1)';
	fieldname=char(fieldname);
	time=fread(fid,1,'double');
	step=fread(fid,1,'int');

	type=fread(fid,1,'int');
	M=fread(fid,1,'int');
	if type==1,
		field=fread(fid,M,'double');
	elseif type==2,
		field=fread(fid,M,'char');
		field=char(field(1:end-1)');
	elseif type==3,
		N=fread(fid,1,'int');
		field=transpose(fread(fid,[N M],'double'));
	else
		error(['cannot read data of type ' num2str(type) ]);
	end

	result.fieldname=fieldname;
	result.time=time;
	result.step=step;
	result.field=field;
end
% }}}
function result=ReadDataDimensions(fid) % {{{
%READDATADIMENSIONS - read data dimensions, step and time, but not the data itself.
%
%   Usage:
%      field=ReadDataDimensions(fid)

%read field
[length,count]=fread(fid,1,'int');

if count==0,
	result=struct([]);
else
	fieldname=fread(fid,length,'char');
	fieldname=fieldname(1:end-1)';
	fieldname=char(fieldname);
	time=fread(fid,1,'double');
	step=fread(fid,1,'int');

	type=fread(fid,1,'int');
	M=fread(fid,1,'int');
	N=1; %default
	if type==1,
		fseek(fid,M*8,0);
	elseif type==2,
		fseek(fid,M,0);
	elseif type==3,
		N=fread(fid,1,'int');
		fseek(fid,N*M*8,0);
	else
		error(['cannot read data of type ' num2str(type) ]);
	end

	result.fieldname=fieldname;
	result.time=time;
	result.step=step;
	result.M=M;
	result.N=N;
end
% }}}
