function results = mergeStructsRecursive(varargin)

%  mergeStructsRecursive - Merges given structures into a single structure, merging substructures recursively.
%
% Usage:
% results = mergeStructsRecursive( struct1 [, struct2, ...] )
%
% Parameters:
%	struct(n): A structure.
%
% Returns:
% 	results: The merged structure.
%
% Description:
%   The fields will in earlier arguments will have priority. So, while merging two
% structs, if there are duplicate fields, the fields in the first will be
% preserved. If a common field is a structure, then mergeStructsRecursive
% is called to merge their contents.
%
% Example: 
% >> mergeStructsRecursive( struct('hello', struct('a', 1), 
%			    struct('hello', struct('b', 2)) );
%  => struct('hello', struct('a', 1, 'b', 2)
%
% $Id$
% Author: Cengiz Gunay <cgunay@emory.edu>, 2004/09/13

% Copyright (c) 2007 Cengiz Gunay <cengique@users.sf.net>.
% This work is licensed under the Academic Free License ("AFL")
% v. 3.0. To view a copy of this license, please look at the COPYING
% file distributed with this software or visit
% http://opensource.org/licenses/afl-3.0.php.

valcell = {};
fieldcell = {};

for k=1:nargin
  % Be nice
  if ~isempty(varargin{k})
    fields = fieldnames(varargin{k});
    % find common fields and look for structures
    [commonfields common_idx] = intersect(fieldcell, fields);
    if ~isempty(common_idx)
      for common_id = common_idx(:)'
        left_struct = valcell{common_id};
        if isstruct(left_struct)
          valcell{common_id} = ...
              mergeStructsRecursive(left_struct, getfield(varargin{k}, fieldcell{common_id}));
        end
      end
    end
    % find new fields on right-hand-side argument
    [newfields newidx] = setdiff(fields, fieldcell);
    % add to existing fields and values
    fieldcell = { fieldcell{:}, newfields{:}};
    val = struct2cell(varargin{k});
    valcell = { valcell{:}, val{newidx}};
  end
end

% Be even nicer
if nargin > 0
  results = cell2struct(valcell, fieldcell, 2);
else
  results = struct([]);
end
