function [A, count] = fscanf(fileID, formatSpec, varargin)
%MATLAB Code Generation Library Function

%#codegen
%   Copyright 2019-2023 The MathWorks, Inc.



narginchk(2,3);

if nargin == 3
    coder.internal.assert(coder.internal.isBuiltInNumeric(varargin{1}), ...
        'Coder:toolbox:eml_assert_valid_size_arg_3', ...
        'IfNotConst','Fail');    
    sizeA = floor(full(varargin{1}));
    if (isscalar(sizeA) && ~isinf(sizeA)) || (~isscalar(sizeA) && ~isinf(sizeA(2)))
        coder.internal.assertValidSizeArg(sizeA);
    elseif ~isscalar(sizeA)
        coder.internal.assertValidSizeArg(sizeA(1));
    end
    if isFileIOExtrinsic
        [A, count] = mFscanf(fileID, formatSpec, sizeA);
    else
        if isscalar(sizeA) && isinf(sizeA)
            [A, count] = cFscanf(fileID, formatSpec);
        else
            [A, count] = cFscanf(fileID, formatSpec, sizeA);
        end
    end
else
    if isFileIOExtrinsic
        [A, count] = mFscanf(fileID, formatSpec);
    else
        [A, count] = cFscanf(fileID, formatSpec);
    end
end
end

function [A, count] = mFscanf(varargin)%TODO: is varargin really the right thing?

[~, ~, ~, outType, outTypeEX] = coder.internal.io.preprocessXscanfFmt(varargin{2});
coder.const(outType);
count = 0;

[tmpA, count] = feval('fscanf', varargin{:});

if isempty(tmpA)
   if strcmp(outType, 'char')
       A = repmat(' ', coder.ignoreConst([0,1]));
   else
       A = zeros(coder.ignoreConst([0,1]), outType);
   end
   return;
end

if nargin > 2 && isscalar(varargin{3})
    if (coder.internal.isConst(varargin{3}) || strcmp(outType, 'char') ) && isinf(varargin{3})
        %would eml_expand make this shorter? or something else?
        if strcmp(outType, 'char')
            A = coder.nullcopy(blanks(coder.internal.ignoreRange(0))); %#ok<NASGU>
        else
            A = coder.nullcopy(zeros(coder.internal.ignoreRange(0),1, outType)); %#ok<NASGU>
        end
        A = tmpA;
    elseif isinf(varargin{3}) && ~strcmp(outType, 'char') %we will never be char if the first condition is true anyway, but the compiler needs to be reminded so it isn't worried about cases where A is char
        A = coder.nullcopy(zeros(coder.internal.ignoreRange(0),coder.internal.ignoreRange(1), outType)); %#ok<NASGU>
        A = tmpA;
    else
        
        numelOut = coder.internal.io.getXscanfOutNumel(outTypeEX, varargin{3});
        if strcmp(outType, 'char')
            A = coder.nullcopy(blanks(coder.ignoreConst(numelOut)));%#ok<NASGU>
        else
            %WISH: similar to below, would be nice to refactor and avoid
            %repetition
            providedNumel = varargin{3};
            numelOut = coder.internal.io.getXscanfOutNumel(outTypeEX, providedNumel);
            actualSize = [providedNumel, floor(numelOut/providedNumel)];%NOTE: this could be slightly simplified by using ceil, as the inputs are ints
            if mod(numelOut, providedNumel) > 0
                actualSize(2) = actualSize(2)+1;
            end
            A = coder.nullcopy(zeros(coder.ignoreConst(actualSize), outType));%#ok<NASGU>
        end
        A = tmpA;
    end
elseif nargin > 2
    sz = varargin{3};
    providedNumel = sz(1)* sz(2);
    numelOut = coder.internal.io.getXscanfOutNumel(outTypeEX, providedNumel);
    actualSize = [sz(1), floor(numelOut/sz(1))];%see note about other actual size calculation
    if mod(numelOut, sz(1)) > 0
        actualSize(2) = actualSize(2)+1;
    end
    if isinf(numelOut)
        actualSize = [sz(1), coder.internal.ignoreRange(0)];
    end
    if strcmp(outType, 'char')
        A = coder.nullcopy(repmat(' ', coder.ignoreConst(actualSize)));%#ok<NASGU>
    else
        A = coder.nullcopy(zeros(coder.ignoreConst(actualSize), outType));%#ok<NASGU>
    end
    A = tmpA;
else
    if strcmp(outType, 'char')
        A = coder.nullcopy(blanks(coder.internal.ignoreRange(0))); %#ok<NASGU>
    else
        A = coder.nullcopy(zeros(coder.internal.ignoreRange(0),1, outType)); %#ok<NASGU>
    end
    A = tmpA;
end

end

function [A, count] = cFscanf(fileID, formatSpec, varargin)
fname = 'fscanf';
[A,count] = coder.internal.io.scanf(fileID, formatSpec, fname, varargin{:});

end
