function theBuffer = nc_getbuffer ( ncfile, varargin )
% NC_GETBUFFER:  read the record variables of a netcdf file into a structure
%
% USAGE:  theBuffer = nc_getbuffer ( ncfile );
% USAGE:  theBuffer = nc_getbuffer ( ncfile, varlist );
% USAGE:  theBuffer = nc_getbuffer ( ncfile, start, count );
% USAGE:  theBuffer = nc_getbuffer ( ncfile, varlist, start, count );
%
% PARAMETERS:
% INPUT:
%     ncfile:  
%        Input netcdf file name.
%     varlist:
%        cell array of named variables.  Only data for these variables 
%        will be retrieved from the file
%     start, count:
%        starting index and number of records to retrieve.  This is 
%        optional.  If not provided, all of the record variables will
%        be retrieved.
%        
%        If start is negative, then the last few records (total of
%        "count") are retrieved.
%
%        If count is negative, then everything beginning at "start" 
%        and going all the way to the end is retrieved.
% 
% OUTPUT:
%     theBuffer:
%        Structure with fields corresponding to each netcdf record variable.  
%        Each such field contains the data for that variable.
%
% In case of an error, an exception is thrown.
%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% $Id: nc_getbuffer.m 1740 2006-08-29 16:15:23Z johnevans007 $
% $LastChangedDate: 2006-08-29 12:15:23 -0400 (Tue, 29 Aug 2006) $
% $LastChangedRevision: 1740 $
% $LastChangedBy: johnevans007 $
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%



%
% assume failure until success is known
theBuffer = [];


%
% Check for proper number of input arguments
if nargin < 1 
	error ( '%s:  must have at least one input argument.\n', mfilename );
end
if nargin > 4 
	error ( '%s:  must have no more than four input arguments.\n', mfilename );
end

%
% check that the first argument is a char
if ~ischar ( ncfile )
   	error (  '%s:  first argument must be character.\n', mfilename );
end


%
% figure out what the inputs actually were
start_count_supplied = 0;
varlist_supplied = 0;
switch nargin
case 2
	if iscell(varargin{1})
		varlist = varargin{1};
		varlist_supplied = 1;
	else
		fmt = '%s:  2nd of two input arguments must be a cell array.\n';
		error ( fmt, mfilename );
	end
case 3
	if isnumeric(varargin{1}) && isnumeric(varargin{2})
		start_count_supplied = 1;
		start = varargin{1};
		count = varargin{2};
	else
		error ( '%s:  2nd and 3rd of three input arguments must be numeric.\n', mfilename );
	end
case 4
	if iscell(varargin{1})
		varlist = varargin{1};
		varlist_supplied = 1;
	else
		error ( '%s:  2nd of four input arguments must be a cell array.\n', mfilename );
	end
	if isnumeric(varargin{2}) && isnumeric(varargin{3})
		start_count_supplied = 1;
		start = varargin{2};
		count = varargin{3};
	else
		error ( '%s:  3rd and 4th of four input arguments must be numeric.\n', mfilename );
	end
end



try
	metadata = nc_info ( ncfile );
catch
	fmt = '%s:  nc_info failed on file ''%s'', error ''%s''\n';
	error ( fmt, mfilename, ncfile, lasterr  );
end

num_datasets = length(metadata.DataSet);

if varlist_supplied

	we_dont_want_it = ones(num_datasets,1);

	%
	% Go thru and quickly set up a flag for each DataSet
	for j = 1:num_datasets
		for k = 1:length(varlist)
			if strcmp(varlist{k}, metadata.DataSet(j).Name)
				we_dont_want_it(j) = 0;
			end
		end
	end

else
	we_dont_want_it = zeros(num_datasets,1);
end

retrievable_datasets = find(1 - we_dont_want_it);
if ~any(retrievable_datasets)
	error ( '%s:  No datasets found.\n', mfilename );
end


%
% Find the unlimited dimension and it's length
record_length = -1;
num_dims = length(metadata.Dimension);
for j = 1:num_dims
	if metadata.Dimension(j).Record_Dimension
		record_length = metadata.Dimension(j).Length;
	end
end
if record_length < 0
	error ( '%s:  no unlimited dimension was found.\n', mfilename );
end

%
% figure out what the start and count really are.
if start_count_supplied == 1
	if start < 0
		start = record_length - count;
	end
	if count < 0
		count = record_length - start;
	end
	if (start < 0) && (count < 0)
		error ( '%s:  both start and count cannot be less than zero.\n', mfilename );
	end
end




for j = 1:num_datasets
	
	%
	% Did we restrict retrieval to a few variables?
	if varlist_supplied
		if we_dont_want_it(j)
			continue
		end
	end

	if metadata.DataSet(j).IsUnlimitedVariable

		if start_count_supplied 
			varstart = zeros(size(metadata.DataSet(j).Size));
			varstart(1) = start;
			varcount = metadata.DataSet(j).Size;
			varcount(1) = count;

			try
				vardata = nc_varget ( ncfile, metadata.DataSet(j).Name, varstart, varcount );
			catch
				format = '%s:  nc_varget failed on file %s, variable %s.\n';
				error ( format, mfilename, ncfile, metadata.DataSet(j).Name );
			end

		else
			try
				vardata = nc_varget ( ncfile, metadata.DataSet(j).Name );
			catch
				format = '%s:  nc_varget failed on file %s, variable %s.\n';
				error ( format, mfilename, ncfile, metadata.DataSet(j).Name );
			end
		end


		theBuffer.(metadata.DataSet(j).Name) = vardata;

	end
end


return
