function t = struct2table(s,varargin)  %#codegen
%STRUCT2TABLE Convert structure array to table.
%   T = STRUCT2TABLE(S) converts the structure array S to a table T.  Each field
%   of S becomes a variable in T.  When S is a scalar structure with N fields,
%   all of which have M rows, then T is an M-by-N table.  When S is a non-scalar
%   structure array with M elements and N fields, then T is M-by-N.
%
%   T = STRUCT2TABLE(S, 'PARAM1', VAL1, 'PARAM2', VAL2, ...) specifies optional
%   parameter name/value pairs that determine how the data in S are converted.
%
%      'RowNames'        A cell array of character vectors or string array 
%                        containing row names for T.  The names need not be
%                        valid MATLAB identifiers, but must be unique.
%      'DimensionNames'  A cell array of character vectors or string array 
%                        containing dimension names for T.  The names must be
%                        unique and must not conflict with the variable names. 
%      'AsArray'         A logical value.  Setting this to true causes STRUCT2TABLE
%                        to always convert S to a table with LENGTH(S) rows, and
%                        not treat a scalar structure specially as described above.
%                        Default is false when S is a scalar structure, true otherwise.
%
%   See also TABLE2STRUCT, CELL2TABLE, ARRAY2TABLE, TABLE.

%   Copyright 2012-2021 The MathWorks, Inc.

if ~isempty(coder.target)
    % codegen, redirect to codegen specific function and return
    t = matlab.internal.coder.struct2table(s, varargin{:});
    return
end

if ~isstruct(s)
    error(message('MATLAB:struct2table:NotVector'));
end

if nargin == 1
    rownames = {};
    supplied.RowNames = false;
    supplied.DimensionNames = false;
    supplied.AsArray = false;
else
    pnames = {'RowNames' 'DimensionNames' 'AsArray'};
    dflts =  {       {}               {}        [] };
    [rownames,dimnames,asArray,supplied] ...
        = matlab.internal.datatypes.parseArgs(pnames, dflts, varargin{:});
end

if supplied.AsArray
    asArray = matlab.internal.datatypes.validateLogical(asArray,'AsArray');
    if ~asArray && ~isscalar(s)
        error(message('MATLAB:struct2table:NonScalar'));
    end
else
    asArray = ~isscalar(s);
end

if asArray
    % Because structures grow as rows by default, don't be pedantic about
    % shape.  Accept either a row or a col.
    if ~isvector(s) && ~isempty(s)
        error(message('MATLAB:struct2table:NotVector'));
    end
    
    varnames = fieldnames(s);
    nvars = length(varnames);
    nrows = numel(s);
    
    if nvars == 0
        % Performant special case to create an Nx0 empty table.
        t = table.empty(nrows,0);
        if supplied.RowNames, t.Properties.RowNames = rownames; end
        if supplied.DimensionNames, t.Properties.DimensionNames = dimnames; end
    else
        % Each field of S becomes a variable in T after vertcat'ing the individual
        % values along that field. container2vars ensures that the vars in its
        % output cell are all the same height.
        vars = tabular.container2vars(s); % structArray -> cellVector
        if supplied.DimensionNames
            t = table.init(vars,nrows,rownames,nvars,varnames,dimnames);
        else
            t = table.init(vars,nrows,rownames,nvars,varnames);
        end
    end
else
    if isempty(fieldnames(s)) && supplied.RowNames
        % Size the array according to the row names
        t = table.empty(length(rownames),0);
        if supplied.DimensionNames, t.Properties.DimensionNames = dimnames; end
    else
        try %#ok<EMTC> 
            if supplied.DimensionNames
                t = table.fromScalarStruct(s,rownames,dimnames);
            else
                t = table.fromScalarStruct(s,rownames); 
            end
        catch ME
            matlab.internal.datatypes.throwInstead(ME,'MATLAB:table:UnequalFieldLengths',message('MATLAB:struct2table:UnequalFieldLengths'));
        end
    end
end
