FF_Error_t FF_PopulateLongDirent()

in ff_dir.c [1374:1622]


FF_Error_t FF_PopulateLongDirent( FF_IOManager_t * pxIOManager,
                                  FF_DirEnt_t * pxDirEntry,
                                  uint16_t usEntry,
                                  FF_FetchContext_t * pxFetchContext )
{
/* First get the entire name as UTF-16 from the LFN's.
 *  Then transform into the API's native string format. */

    FF_Error_t xError;
    BaseType_t xNumLFNs;
    uint8_t ucCheckSum;
/* A 32 byte directory entry. */
    uint8_t pucEntryBuffer[ FF_SIZEOF_DIRECTORY_ENTRY ];
    char pcShortName[ 13 ];

    #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
        UBaseType_t uiLfnLength = 0;
    #endif

    #if ( ffconfigUNICODE_UTF16_SUPPORT == 0 )
        BaseType_t xIndex, y;
    #endif

    #if ( ffconfigUNICODE_UTF16_SUPPORT == 0 ) && ( ffconfigUNICODE_UTF8_SUPPORT == 0 )
        char * pcLastPtr = pxDirEntry->pcFileName + sizeof( pxDirEntry->pcFileName );
        char * pcCurPtr;
    #endif

    #if ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
        uint16_t nLfnBegin;
        uint16_t usUtf8Len = 0;
    #endif /* ffconfigUNICODE_UTF8_SUPPORT */

    do
    {
        xError = FF_FetchEntryWithContext( pxIOManager, usEntry++, pxFetchContext, pucEntryBuffer );

        if( FF_isERR( xError ) )
        {
            /* After breaking from this do {} while ( pdFALSE ) loop, xResult will be returned. */
            break;
        }

        xNumLFNs = ( BaseType_t ) ( pucEntryBuffer[ 0 ] & ~0x40 );
        ucCheckSum = FF_getChar( pucEntryBuffer, FF_FAT_LFN_CHECKSUM );

        #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
            {
                /* UTF-16 Can simply get segments of the UTF-16 sequence
                 * going forward in the directory entries ( but reversed order ). */
                while( xNumLFNs > 0 )
                {
                    /* Avoid stack intensive use of a UTF-16 buffer. Stream direct to FileName dirent field in correct format. */
                    /* memcpy direct! -UTF-16 support. */
                    memcpy( pxDirEntry->pcFileName + ( ( xNumLFNs - 1 ) * 13 ) + 0, &( pucEntryBuffer[ FF_FAT_LFN_NAME_1 ] ), 10 );
                    memcpy( pxDirEntry->pcFileName + ( ( xNumLFNs - 1 ) * 13 ) + 5, &( pucEntryBuffer[ FF_FAT_LFN_NAME_2 ] ), 12 );
                    memcpy( pxDirEntry->pcFileName + ( ( xNumLFNs - 1 ) * 13 ) + 11, &( pucEntryBuffer[ FF_FAT_LFN_NAME_3 ] ), 4 );
                    uiLfnLength += 13;

                    xError = FF_FetchEntryWithContext( pxIOManager, usEntry++, pxFetchContext, pucEntryBuffer );

                    if( FF_isERR( xError ) )
                    {
                        break;
                    }

                    xNumLFNs--;
                }

                if( FF_isERR( xError ) )
                {
                    break;
                }

                pxDirEntry->pcFileName[ uiLfnLength ] = '\0';
            }
        #endif /* ffconfigUNICODE_UTF16_SUPPORT */

        #if ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
            {
                /* UTF-8 Sequence, we can only convert this from the beginning, must receive entries in reverse. */
                nLfnBegin = usEntry - 1;

                for( xIndex = 0; xIndex < xNumLFNs; xIndex++ )
                {
                    xError = FF_FetchEntryWithContext( pxIOManager, ( nLfnBegin + ( xNumLFNs - 1 ) - xIndex ), pxFetchContext, pucEntryBuffer );

                    if( FF_isERR( xError ) )
                    {
                        break;
                    }

                    /* Now have the first part of the UTF-16 sequence. Stream into a UTF-8 sequence. */
                    for( y = 0; y < 5; y++ )
                    {
                        xError = FF_Utf16ctoUtf8c( ( uint8_t * ) &pxDirEntry->pcFileName[ usUtf8Len ],
                                                   ( uint16_t * ) &pucEntryBuffer[ FF_FAT_LFN_NAME_1 + ( y * 2 ) ], sizeof( pxDirEntry->pcFileName ) - usUtf8Len );

                        if( xError > 0 )
                        {
                            usUtf8Len += ( uint16_t ) xError;
                        }
                    }

                    for( y = 0; y < 6; y++ )
                    {
                        xError = FF_Utf16ctoUtf8c( ( uint8_t * ) &pxDirEntry->pcFileName[ usUtf8Len ],
                                                   ( uint16_t * ) &pucEntryBuffer[ FF_FAT_LFN_NAME_2 + ( y * 2 ) ], sizeof( pxDirEntry->pcFileName ) - usUtf8Len );

                        if( xError > 0 )
                        {
                            usUtf8Len += ( uint16_t ) xError;
                        }
                    }

                    for( y = 0; y < 2; y++ )
                    {
                        xError = FF_Utf16ctoUtf8c( ( uint8_t * ) &pxDirEntry->pcFileName[ usUtf8Len ],
                                                   ( uint16_t * ) &pucEntryBuffer[ FF_FAT_LFN_NAME_3 + ( y * 2 ) ], sizeof( pxDirEntry->pcFileName ) - usUtf8Len );

                        if( xError > 0 )
                        {
                            usUtf8Len += ( uint16_t ) xError;
                        }
                    }

                    usEntry++;
                }

                if( FF_isERR( xError ) )
                {
                    break;
                }

                pxDirEntry->pcFileName[ usUtf8Len ] = '\0';

                /* Put Entry context to correct position. */
                xError = FF_FetchEntryWithContext( pxIOManager, usEntry - 1, pxFetchContext, pucEntryBuffer );

                if( FF_isERR( xError ) )
                {
                    break;
                }
            }
        #endif /* ( ffconfigUNICODE_UTF8_SUPPORT != 0 ) */

        #if ( ffconfigUNICODE_UTF16_SUPPORT == 0 ) && ( ffconfigUNICODE_UTF8_SUPPORT == 0 ) /* No Unicode, simple ASCII. */
            {
                pcLastPtr[ -1 ] = '\0';
                y = xNumLFNs;

                while( xNumLFNs-- )
                {
                    pcCurPtr = pxDirEntry->pcFileName + ( xNumLFNs * 13 );

                    for( xIndex = 0; ( xIndex < 10 ) && ( pcCurPtr < pcLastPtr ); xIndex += 2 )
                    {
                        *( pcCurPtr++ ) = pucEntryBuffer[ FF_FAT_LFN_NAME_1 + xIndex ];
                    }

                    for( xIndex = 0; ( xIndex < 12 ) && ( pcCurPtr < pcLastPtr ); xIndex += 2 )
                    {
                        *( pcCurPtr++ ) = pucEntryBuffer[ FF_FAT_LFN_NAME_2 + xIndex ];
                    }

                    for( xIndex = 0; ( xIndex < 4 ) && ( pcCurPtr < pcLastPtr ); xIndex += 2 )
                    {
                        *( pcCurPtr++ ) = pucEntryBuffer[ FF_FAT_LFN_NAME_3 + xIndex ];
                    }

                    if( ( xNumLFNs == ( y - 1 ) ) && ( pcCurPtr < pcLastPtr ) )
                    {
                        *pcCurPtr = '\0';
                    }

                    xError = FF_FetchEntryWithContext( pxIOManager, usEntry++, pxFetchContext, pucEntryBuffer );

                    if( FF_isERR( xError ) )
                    {
                        break;
                    }
                }

                if( FF_isERR( xError ) )
                {
                    break;
                }
            }
        #endif /* ( ffconfigUNICODE_UTF16_SUPPORT == 0 ) && ( ffconfigUNICODE_UTF8_SUPPORT == 0 ) */

        /* Process the Shortname. -- LFN Transformation is now complete.
         * Process the ShortName Entry. */

        /* if SHORTNAMES must be included, simple byte copy into shortname buffer. */
        #if ( ffconfigLFN_SUPPORT != 0 ) && ( ffconfigINCLUDE_SHORT_NAME != 0 )
            {
                memcpy( pxDirEntry->pcShortName, pucEntryBuffer, 11 );
                pxDirEntry->pcShortName[ 11 ] = '\0';
                FF_ProcessShortName( pxDirEntry->pcShortName );
            }
        #endif /* ( != 0 ffconfigLFN_SUPPORT ) && ( ffconfigINCLUDE_SHORT_NAME != 0 ) */

        memcpy( pcShortName, pucEntryBuffer, 11 );
        FF_ProcessShortName( pcShortName );

        if( ucCheckSum != FF_CreateChkSum( pucEntryBuffer ) )
        {
            strcpy( pxDirEntry->pcFileName, pcShortName );
            #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
                {
                    FF_ShortNameExpand( pxDirEntry->pcFileName );
                }
            #endif /* ffconfigUNICODE_UTF16_SUPPORT */
        }

        /* Finally fill in the other details. */
        pxDirEntry->ulObjectCluster =
            ( ( uint32_t ) FF_getShort( pucEntryBuffer, FF_FAT_DIRENT_CLUS_HIGH ) << 16 ) |
            ( uint32_t ) FF_getShort( pucEntryBuffer, FF_FAT_DIRENT_CLUS_LOW );

        #if ( ffconfigTIME_SUPPORT != 0 )
            {
                /* Get the creation Time & Date. */
                FF_GetTime( &pxDirEntry->xCreateTime, pucEntryBuffer, FF_FAT_DIRENT_CREATE_TIME );
                FF_GetDate( &pxDirEntry->xCreateTime, pucEntryBuffer, FF_FAT_DIRENT_CREATE_DATE );
                /* Get the modified Time & Date. */
                /* HT Here xCreateTime has become xModifiedTime, as it should: */
                FF_GetTime( &pxDirEntry->xModifiedTime, pucEntryBuffer, FF_FAT_DIRENT_LASTMOD_TIME );
                FF_GetDate( &pxDirEntry->xModifiedTime, pucEntryBuffer, FF_FAT_DIRENT_LASTMOD_DATE );
                /* Get the last accessed Date. */
                FF_GetDate( &pxDirEntry->xAccessedTime, pucEntryBuffer, FF_FAT_DIRENT_LASTACC_DATE );
                /* HT Why should these times be zero'd ? */
                pxDirEntry->xAccessedTime.Hour = 0;
                pxDirEntry->xAccessedTime.Minute = 0;
                pxDirEntry->xAccessedTime.Second = 0;
            }
        #endif /* ffconfigTIME_SUPPORT */

        /* Get the filesize. */
        pxDirEntry->ulFileSize = FF_getLong( pucEntryBuffer, ( uint16_t ) ( FF_FAT_DIRENT_FILESIZE ) );
        /* Get the attribute. */
        pxDirEntry->ucAttrib = FF_getChar( pucEntryBuffer, ( uint16_t ) ( FF_FAT_DIRENT_ATTRIB ) );

        pxDirEntry->usCurrentItem = usEntry;
    }
    while( pdFALSE );

    return xError;
}   /* FF_PopulateLongDirent() */