function o = optimget(options,name,default,flag)
%MATLAB Code Generation Library Function

% The code generation version guarantees that the returned value has a fixed
% size to facilitate constant-folding of ISEMPTY checks.  Structs with
% variable-sized fields are permitted as long as those fields are not accessed.
% 
% Limitations:
%   1. The name argument must be constant.

%   Copyright 2013-2016 The MathWorks, Inc.
%#codegen
narginchk(2,4);

if nargin == 4 && strcmp(flag,'fast')
    % Undocumented syntax taking a default options struct and with no matching/error
    % checking on name.
    coder.internal.prefer_const(default,flag);
    if isstring(name)
        o = optimgetinternal(options,char(name),default);
    else
        o = optimgetinternal(options,name,default);
    end
else
    eml_invariant(isstruct(options) || isempty(options), 'MATLAB:optimfun:optimget:Arg1NotStruct');
    eml_invariant(eml_is_const(name), 'Coder:toolbox:OptimgetConstName');
    coder.internal.prefer_const(options,name);

    % Standard syntax with a non-struct default value.  Include partial matching
    % logic.
    if nargin < 3
        default = defaultOpt();
    else
        coder.internal.prefer_const(default);
    end

    if isempty(options)
        o = default;
    else
        % Get property names and user provided name as a row
        pnames = optimOptNames();
        if isstring(name)
            paramname = deblank(char(name));
        else
            paramname = deblank(name(:)');
        end

        % Get the option value
        o = coder.internal.partialParamParser(paramname, name, pnames, options, default, ['optimfun:', mfilename]);
    end
end

% Require fixed-size field values
eml_invariant(eml_is_const(size(o)), ...
                      'Coder:toolbox:OptimsetgetFixedSizeFields', ...
                      name, ...
                      'IfNotConst', 'Fail');

%--------------------------------------------------------------------------

function o = optimgetinternal(options,name,default)
% Internal version which doesn't error-check the name argument.  If the field
% name of options is non-empty we return that otherwise the field name of the
% options struct default is returned instead.
coder.inline('always');
coder.internal.prefer_const(options,name,default);
if isempty(options)
    ot = default.(name);
else
    if isfield(options,name) && ~isempty(options.(name))
        ot = options.(name);
    else
        ot = default.(name);
    end
end
if isstring(ot)
    o = char(ot);
else
    o = ot;
end

%--------------------------------------------------------------------------
