int32_t FF_Read()

in ff_file.c [1732:1952]


int32_t FF_Read( FF_FILE * pxFile,
                 uint32_t ulElementSize,
                 uint32_t ulCount,
                 uint8_t * pucBuffer )
{
    uint32_t ulBytesLeft = ulElementSize * ulCount;
    uint32_t ulBytesRead = 0;
    uint32_t ulBytesToRead;
    FF_IOManager_t * pxIOManager;
    uint32_t ulRelBlockPos;
    uint32_t ulItemLBA;
    int32_t lResult;
    uint32_t ulSectors;
    uint32_t ulRelClusterPos;
    uint32_t ulBytesPerCluster;
    FF_Error_t xError;

    if( pxFile == NULL )
    {
        xError = ( FF_Error_t ) ( FF_ERR_NULL_POINTER | FF_READ );
    }
    else
    {
        /* Check validity of the handle and the current position within the file. */
        xError = FF_CheckValid( pxFile );

        if( FF_isERR( xError ) == pdFALSE )
        {
            if( ( pxFile->ucMode & FF_MODE_READ ) == 0 )
            {
                /* File was not opened with READ mode access. */
                xError = ( FF_Error_t ) ( FF_ERR_FILE_NOT_OPENED_IN_READ_MODE | FF_READ );
            }
            else if( pxFile->ulFilePointer >= pxFile->ulFileSize )
            {
                /* The end-of-file is reached.  The error READ_ZERO will not be
                 * returned, it is just used to avoid further processing. */
                xError = ( FF_Error_t ) ( FF_ERR_FILE_READ_ZERO | FF_READ );
            }
            else if( ( pxFile->ulFilePointer + ulBytesLeft ) > pxFile->ulFileSize )
            {
                /* Note that many bytes can be read. */
                ulBytesLeft = pxFile->ulFileSize - pxFile->ulFilePointer;
            }
        }
        else
        {
            /* The file handle is not valid. */
        }
    }   /* else pxFile != NULL */

    if( FF_isERR( xError ) == pdFALSE )
    {
        pxIOManager = pxFile->pxIOManager;

        /* And calculate the Logical Block Address. */
        ulItemLBA = FF_SetCluster( pxFile, &xError );

        /* Get the position within a block. */
        ulRelBlockPos = FF_getMinorBlockEntry( pxIOManager, pxFile->ulFilePointer, 1 );

        /* Open a do {} while( 0 ) loop to allow easy breaks: */
        do
        {
            if( ( ulRelBlockPos + ulBytesLeft ) <= ( uint32_t ) pxIOManager->usSectorSize )
            {
                /*---------- A small read within the current block only. */
                ulBytesRead = FF_ReadPartial( pxFile, ulItemLBA, ulRelBlockPos, ulBytesLeft, pucBuffer, &xError );
                break;
            }

            /*---------- Read (memcpy) to a Sector Boundary. */
            if( ulRelBlockPos != 0 )
            {
                /* Not on a sector boundary, at this point the LBA is known. */
                ulBytesToRead = pxIOManager->usSectorSize - ulRelBlockPos;
                ulBytesRead = FF_ReadPartial( pxFile, ulItemLBA, ulRelBlockPos, ulBytesToRead, pucBuffer, &xError );

                if( FF_isERR( xError ) )
                {
                    break;
                }

                ulBytesLeft -= ulBytesRead;
                pucBuffer += ulBytesRead;
            }

            /*---------- Read sectors, up to a Cluster Boundary. */
            ulBytesPerCluster = ( pxIOManager->xPartition.ulSectorsPerCluster * pxIOManager->usSectorSize );
            ulRelClusterPos = pxFile->ulFilePointer % ( ulBytesPerCluster * pxIOManager->xPartition.ucBlkFactor );

            if( ( ulRelClusterPos != 0 ) && ( ( ulRelClusterPos + ulBytesLeft ) >= ulBytesPerCluster ) )
            {
                /* Need to get to cluster boundary. */
                ulItemLBA = FF_SetCluster( pxFile, &xError );

                if( FF_isERR( xError ) )
                {
                    break;
                }

                ulSectors = pxIOManager->xPartition.ulSectorsPerCluster - ( ulRelClusterPos / pxIOManager->usSectorSize );
                xError = FF_BlockRead( pxIOManager, ulItemLBA, ulSectors, pucBuffer, pdFALSE );

                if( FF_isERR( xError ) )
                {
                    break;
                }

                ulBytesToRead = ulSectors * pxIOManager->usSectorSize;
                ulBytesLeft -= ulBytesToRead;
                pucBuffer += ulBytesToRead;
                ulBytesRead += ulBytesToRead;
                pxFile->ulFilePointer += ulBytesToRead;
            }

            /*---------- Read entire clusters. */
            if( ulBytesLeft >= ulBytesPerCluster )
            {
                uint32_t ulClusters;

                FF_SetCluster( pxFile, &xError );

                if( FF_isERR( xError ) )
                {
                    break;
                }

                ulClusters = ulBytesLeft / ulBytesPerCluster;

                xError = FF_ReadClusters( pxFile, ulClusters, pucBuffer );

                if( FF_isERR( xError ) )
                {
                    break;
                }

                ulBytesToRead = ulBytesPerCluster * ulClusters;
                pxFile->ulFilePointer += ulBytesToRead;
                ulBytesLeft -= ulBytesToRead;
                pucBuffer += ulBytesToRead;
                ulBytesRead += ulBytesToRead;
            }

            /*---------- Read Remaining Blocks. */
            while( ulBytesLeft >= ( uint32_t ) pxIOManager->usSectorSize )
            {
                ulSectors = ulBytesLeft / pxIOManager->usSectorSize;
                {
                    /* HT: I'd leave these pPart/ulOffset for readability */
                    /* and shorter code lines */
                    FF_Partition_t * pPart = &( pxIOManager->xPartition );
                    uint32_t ulOffset = ( pxFile->ulFilePointer / pxIOManager->usSectorSize ) % pPart->ulSectorsPerCluster;
                    uint32_t ulRemain = pPart->ulSectorsPerCluster - ulOffset;

                    if( ulSectors > ulRemain )
                    {
                        ulSectors = ulRemain;
                    }
                }

                ulItemLBA = FF_SetCluster( pxFile, &xError );

                if( FF_isERR( xError ) )
                {
                    break;
                }

                xError = FF_BlockRead( pxIOManager, ulItemLBA, ulSectors, pucBuffer, pdFALSE );

                if( FF_isERR( xError ) )
                {
                    break;
                }

                ulBytesToRead = ulSectors * pxIOManager->usSectorSize;
                pxFile->ulFilePointer += ulBytesToRead;
                ulBytesLeft -= ulBytesToRead;
                pucBuffer += ulBytesToRead;
                ulBytesRead += ulBytesToRead;
            }

            /*---------- Read (memcpy) Remaining Bytes */
            if( ulBytesLeft == 0 )
            {
                break;
            }

            ulItemLBA = FF_SetCluster( pxFile, &xError );

            if( FF_isERR( xError ) )
            {
                break;
            }

            /* Bytes to read are within a block and less than a block size. */
            FF_ReadPartial( pxFile, ulItemLBA, 0, ulBytesLeft, pucBuffer, &xError );

            if( FF_isERR( xError ) == pdFALSE )
            {
                ulBytesRead += ulBytesLeft;
            }
        }
        while( pdFALSE );
    } /* if( FF_isERR( xError ) == pdFALSE ) */

    if( FF_GETERROR( xError ) == FF_ERR_FILE_READ_ZERO )
    {
        lResult = 0;
    }
    else if( FF_isERR( xError ) )
    {
        lResult = xError;
    }
    else
    {
        lResult = ( int32_t ) ( ulBytesRead / ulElementSize );
    }

    return lResult;
}   /* FF_Read() */