function status = fseek(fileID, offset, origin)
%MATLAB Code Generation Library Function

%   Copyright 2016 The MathWorks, Inc.

%#codegen
narginchk(3,3);
if isFileIOExtrinsic
    status = 0;
    status = feval('fseek', fileID, offset, origin);
else
    status = cfseek(fileID, offset, coder.internal.toCharIfString(origin));
end

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

function status = cfseek(fileID, offset, origin)
coder.cinclude('<stdio.h>');
coder.internal.assert(coder.internal.isCharOrScalarString(origin) || isa(origin, 'double'), ...
                      'MATLAB:fseek:originMustBeDouble');
ZERO = coder.internal.indexInt(0);
switch origin
  case {-1, 'bof'}
    wherefrom = coder.opaque('int','SEEK_SET','HeaderFile','<stdio.h>');
  case {0, 'cof'}
    wherefrom = coder.opaque('int','SEEK_CUR','HeaderFile','<stdio.h>');
  case {1, 'eof'}
    wherefrom = coder.opaque('int','SEEK_END','HeaderFile','<stdio.h>');
  otherwise
    if coder.internal.isConst(origin)
        coder.internal.assert(false, 'MATLAB:badorigin_mx');
    else
        coder.internal.error('MATLAB:badorigin_mx');
    end
end
coder.internal.assert(coder.internal.isBuiltInNumeric(offset), ...
                      'MATLAB:fseek:offsetMustBeDouble');
if isValidOffset(offset)
    fidCheck(fileID, mfilename);
    filestar = getFileStar(fileID);
    if filestar == NULL
        status = STATUS_FAIL;
    else
        status_int = ZERO;
        offset_int = cast(offset, 'like', coder.opaque('long int', '0'));
        status_int = coder.ceval('fseek', filestar, offset_int, wherefrom);
        if status_int == ZERO
            status = STATUS_SUCCESS;
        else
            status = STATUS_FAIL;
        end
    end
else
    status = STATUS_FAIL;
end

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

function p = isValidOffset(n)
coder.inline('always');
p = isfinite(n) && (isinteger(n) || floor(n) == n);

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

function y = STATUS_FAIL
coder.inline('always');
y = -1;

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

function y = STATUS_SUCCESS
coder.inline('always');
y = 0;

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

function filestar = getFileStar(fileID)
% FSEEK not supported on stdin.  Return NULL on error and report the error if
% possible

% Get the FILE * and assert validity
filestar = fileManager('filestar', fileID);
if (coder.internal.hasRuntimeErrors() && filestar == NULL)
    coder.internal.error('MATLAB:FileIO:InvalidFid');
end

% FSEEK not supported for stdin, stdout or stderr
if (~isImplementedFilestar(fileID))
    filestar = NULL;
end

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

function p = isImplementedFilestar(fileID)
coder.inline('always');
p = fileID ~= 0 && fileID ~= 1 && fileID ~= 2;

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

function y = NULL
coder.inline('always');
y = coder.opaque('FILE *','NULL','HeaderFile','<stdio.h>');

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