fatfs/src/ff.c
FRESULT f_forward (
	FIL* fp, 						/* Pointer to the file object */
	UINT (*func)(const BYTE*,UINT),	/* Pointer to the streaming function */
	UINT btf,						/* Number of bytes to forward */
	UINT* bf						/* Pointer to number of bytes forwarded */
)
{
	FRESULT res;
	FATFS *fs;
	DWORD clst, sect;
	FSIZE_t remain;
	UINT rcnt, csect;
	BYTE *dbuf;


	*bf = 0;	/* Clear transfer byte counter */
	res = validate(&fp->obj, &fs);		/* Check validity of the file object */
	if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
	if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED);	/* Check access mode */

	remain = fp->obj.objsize - fp->fptr;
	if (btf > remain) btf = (UINT)remain;			/* Truncate btf by remaining bytes */

	for ( ;  btf && (*func)(0, 0);					/* Repeat until all data transferred or stream goes busy */
		fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) {
		csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1));	/* Sector offset in the cluster */
		if (fp->fptr % SS(fs) == 0) {				/* On the sector boundary? */
			if (csect == 0) {						/* On the cluster boundary? */
				clst = (fp->fptr == 0) ?			/* On the top of the file? */
					fp->obj.sclust : get_fat(&fp->obj, fp->clust);
				if (clst <= 1) ABORT(fs, FR_INT_ERR);
				if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
				fp->clust = clst;					/* Update current cluster */
			}
		}
		sect = clst2sect(fs, fp->clust);			/* Get current data sector */
		if (sect == 0) ABORT(fs, FR_INT_ERR);
		sect += csect;
#if FF_FS_TINY
		if (move_window(fs, sect) != FR_OK) ABORT(fs, FR_DISK_ERR);	/* Move sector window to the file data */
		dbuf = fs->win;
#else
		if (fp->sect != sect) {		/* Fill sector cache with file data */
#if !FF_FS_READONLY
			if (fp->flag & FA_DIRTY) {		/* Write-back dirty sector cache */
				if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
				fp->flag &= (BYTE)~FA_DIRTY;
			}
#endif
			if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
		}
		dbuf = fp->buf;
#endif
		fp->sect = sect;
		rcnt = SS(fs) - (UINT)fp->fptr % SS(fs);	/* Number of bytes left in the sector */
		if (rcnt > btf) rcnt = btf;					/* Clip it by btr if needed */
		rcnt = (*func)(dbuf + ((UINT)fp->fptr % SS(fs)), rcnt);	/* Forward the file data */
		if (rcnt == 0) ABORT(fs, FR_INT_ERR);
	}

	LEAVE_FF(fs, FR_OK);
}
/*-----------------------------------------------------------------------*/
/* Forward Data to the Stream Directly                                   */
/*-----------------------------------------------------------------------*/
Forward Data to the Stream Directly
Forward Data to the Stream Directly
FRESULT f_forward (
	FIL* fp, 						
	UINT (*func)(const BYTE*,UINT),	
	UINT btf,						
	UINT* bf						
)
{
	FRESULT res;
	FATFS *fs;
	DWORD clst, sect;
	FSIZE_t remain;
	UINT rcnt, csect;
	BYTE *dbuf;
	*bf = 0;	
	res = validate(&fp->obj, &fs);		
	if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
	if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED);	
	remain = fp->obj.objsize - fp->fptr;
	if (btf > remain) btf = (UINT)remain;			
	for ( ;  btf && (*func)(0, 0);					
		fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) {
		csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1));	
		if (fp->fptr % SS(fs) == 0) {				
			if (csect == 0) {						
				clst = (fp->fptr == 0) ?			
					fp->obj.sclust : get_fat(&fp->obj, fp->clust);
				if (clst <= 1) ABORT(fs, FR_INT_ERR);
				if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
				fp->clust = clst;					
			}
		}
		sect = clst2sect(fs, fp->clust);			
		if (sect == 0) ABORT(fs, FR_INT_ERR);
		sect += csect;
#if FF_FS_TINY
		if (move_window(fs, sect) != FR_OK) ABORT(fs, FR_DISK_ERR);	
		dbuf = fs->win;
#else
		if (fp->sect != sect) {		
#if !FF_FS_READONLY
			if (fp->flag & FA_DIRTY) {		
				if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
				fp->flag &= (BYTE)~FA_DIRTY;
			}
#endif
			if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
		}
		dbuf = fp->buf;
#endif
		fp->sect = sect;
		rcnt = SS(fs) - (UINT)fp->fptr % SS(fs);	
		if (rcnt > btf) rcnt = btf;					
		rcnt = (*func)(dbuf + ((UINT)fp->fptr % SS(fs)), rcnt);	
		if (rcnt == 0) ABORT(fs, FR_INT_ERR);
	}
	LEAVE_FF(fs, FR_OK);
}
FRESULT f_forward ( FIL * fp , UINT ( * func ) ( const BYTE * , UINT ) , UINT btf , UINT * bf ) { FRESULT res ; FATFS * fs ; DWORD clst , sect ; FSIZE_t remain ; UINT rcnt , csect ; BYTE * dbuf ; * bf = 0 ; res = validate ( & fp -> obj , & fs ) ; if ( res != FR_OK || ( res = ( FRESULT ) fp -> err ) != FR_OK ) LEAVE_FF ( fs , res ) ; if ( ! ( fp -> flag & FA_READ ) ) LEAVE_FF ( fs , FR_DENIED ) ; remain = fp -> obj . objsize - fp -> fptr ; if ( btf > remain ) btf = ( UINT ) remain ; for ( ; btf && ( * func ) ( 0 , 0 ) ; fp -> fptr += rcnt , * bf += rcnt , btf -= rcnt ) { csect = ( UINT ) ( fp -> fptr / SS ( fs ) & ( fs -> csize - 1 ) ) ; if ( fp -> fptr % SS ( fs ) == 0 ) { if ( csect == 0 ) { clst = ( fp -> fptr == 0 ) ? fp -> obj . sclust : get_fat ( & fp -> obj , fp -> clust ) ; if ( clst <= 1 ) ABORT ( fs , FR_INT_ERR ) ; if ( clst == 0xFFFFFFFF ) ABORT ( fs , FR_DISK_ERR ) ; fp -> clust = clst ; } } sect = clst2sect ( fs , fp -> clust ) ; if ( sect == 0 ) ABORT ( fs , FR_INT_ERR ) ; sect += csect ; #if FF_FS_TINY if ( move_window ( fs , sect ) != FR_OK ) ABORT ( fs , FR_DISK_ERR ) ; dbuf = fs -> win ; #else if ( fp -> sect != sect ) { #if ! FF_FS_READONLY if ( fp -> flag & FA_DIRTY ) { if ( disk_write ( fs -> pdrv , fp -> buf , fp -> sect , 1 ) != RES_OK ) ABORT ( fs , FR_DISK_ERR ) ; fp -> flag &= ( BYTE ) ~ FA_DIRTY ; } #endif if ( disk_read ( fs -> pdrv , fp -> buf , sect , 1 ) != RES_OK ) ABORT ( fs , FR_DISK_ERR ) ; } dbuf = fp -> buf ; #endif fp -> sect = sect ; rcnt = SS ( fs ) - ( UINT ) fp -> fptr % SS ( fs ) ; if ( rcnt > btf ) rcnt = btf ; rcnt = ( * func ) ( dbuf + ( ( UINT ) fp -> fptr % SS ( fs ) ) , rcnt ) ; if ( rcnt == 0 ) ABORT ( fs , FR_INT_ERR ) ; } LEAVE_FF ( fs , FR_OK ) ; }
Forward Data to the Stream Directly
Forward Data to the Stream Directly
/* Pointer to the file object */ /* Pointer to the streaming function */ /* Number of bytes to forward */ /* Pointer to number of bytes forwarded */ /* Clear transfer byte counter */ /* Check validity of the file object */ /* Check access mode */ /* Truncate btf by remaining bytes */ /* Repeat until all data transferred or stream goes busy */ /* Sector offset in the cluster */ /* On the sector boundary? */ /* On the cluster boundary? */ /* On the top of the file? */ /* Update current cluster */ /* Get current data sector */ /* Move sector window to the file data */ /* Fill sector cache with file data */ /* Write-back dirty sector cache */ /* Number of bytes left in the sector */ /* Clip it by btr if needed */ /* Forward the file data */