<commit_before>
// ---------------------------------------------------
// The FDiffDelete Project
// Github: https://github.com/shishir993/fdiffdelete
// Author: <NAME>
// The MIT License (MIT)
// Copyright (c) 2014
//

#include "FileInfo.h"

static HCRYPTPROV g_hCrypt = NULL;

HRESULT FileInfoInit(_In_ BOOL fComputeHash)
{
    HRESULT hr = S_OK;
    if(fComputeHash && g_hCrypt == NULL)
    {
        hr = HashFactoryInit(&g_hCrypt);
    }
    return hr;
}

void FileInfoDestroy()
{
    if(g_hCrypt)
    {
        HashFactoryDestroy(g_hCrypt);
        g_hCrypt = NULL;
    }
}

// Populate file info for the specified file in the caller specified memory location
BOOL CreateFileInfo(_In_ PCWSTR pszFullpathToFile, _In_ BOOL fComputeHash, _In_ PFILEINFO pFileInfo)
{
    SB_ASSERT(pszFullpathToFile);
    SB_ASSERT(pFileInfo);

    ZeroMemory(pFileInfo, sizeof(*pFileInfo));

    // Copy file/dir name over to the FILEINFO struct
    PCWSTR pszFilename = CHL_SzGetFilenameFromPath(pszFullpathToFile, wcslen(pszFullpathToFile));
    int nCharsInRoot = 0;
    for (const WCHAR* pch = pszFullpathToFile; pch != pszFilename; ++pch, ++nCharsInRoot)
        ;
    
    // Copy folder path first (we've calculate the length to copy)
    wcsncpy_s(pFileInfo->szPath, ARRAYSIZE(pFileInfo->szPath), pszFullpathToFile, nCharsInRoot);
    
    // Now copy the filename
    wcscpy_s(pFileInfo->szFilename, ARRAYSIZE(pFileInfo->szFilename), pszFilename);

    // Check if file is a directory
    // TODO: To extend this limit to 32,767 wide characters, 
    // call the Unicode version of the function and prepend "\\?\" to the path
    DWORD dwAttr = GetFileAttributes(pszFullpathToFile);
    if(dwAttr == INVALID_FILE_ATTRIBUTES)
    {
        logerr(L"Unable to get attributes of file: %s", pszFullpathToFile);
        goto error_return;
    }

    if(dwAttr & FILE_ATTRIBUTE_DIRECTORY)
    {
        pFileInfo->fIsDirectory = TRUE;
    }
    
    WIN32_FILE_ATTRIBUTE_DATA fileAttr;
    if(!GetFileAttributesEx(pszFullpathToFile, GetFileExInfoStandard, &fileAttr))
    {
        logerr(L"Unable to get attributes of file: %s", pszFullpathToFile);
        goto error_return;
    }

    if(fileAttr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
    {
        pFileInfo->fIsDirectory = TRUE;
    }
    else
    {
        // Store filesize, last access time in fileinfo

        pFileInfo->llFilesize.HighPart = fileAttr.nFileSizeHigh;
        pFileInfo->llFilesize.LowPart = fileAttr.nFileSizeLow;

        // Store FILETIME in fileinfo for easy comparison in sorting the listview rows
        CopyMemory(&pFileInfo->ftModifiedTime, &fileAttr.ftLastWriteTime, sizeof(pFileInfo->ftModifiedTime));

        // Convert filetime to localtime and store in fileinfo
        SYSTEMTIME stUTC;
        FileTimeToSystemTime(&pFileInfo->ftModifiedTime, &stUTC);
        SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &pFileInfo->stModifiedTime);

        if(fComputeHash)
        {
            // Generate hash. Open file handle first...    
            HANDLE hFile = CreateFileW(pszFullpathToFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
            if(hFile == INVALID_HANDLE_VALUE)
            {
                logerr(L"Failed to open file %s", pszFullpathToFile);
                goto error_return;
            }

            HRESULT hr = CalculateSHA1(g_hCrypt, hFile, pFileInfo->abHash);
            CloseHandle(hFile);
            if(FAILED(hr))
            {
                logerr(L"Failed to compute hash (0x%08x) for file: %s", hr, pszFullpathToFile);
                goto error_return;
            }
        }
    }<commit_msg>Show modified time for folders as well<commit_after>
// ---------------------------------------------------
// The FDiffDelete Project
// Github: https://github.com/shishir993/fdiffdelete
// Author: <NAME>
// The MIT License (MIT)
// Copyright (c) 2014
//

#include "FileInfo.h"

static HCRYPTPROV g_hCrypt = NULL;

HRESULT FileInfoInit(_In_ BOOL fComputeHash)
{
    HRESULT hr = S_OK;
    if(fComputeHash && g_hCrypt == NULL)
    {
        hr = HashFactoryInit(&g_hCrypt);
    }
    return hr;
}

void FileInfoDestroy()
{
    if(g_hCrypt)
    {
        HashFactoryDestroy(g_hCrypt);
        g_hCrypt = NULL;
    }
}

// Populate file info for the specified file in the caller specified memory location
BOOL CreateFileInfo(_In_ PCWSTR pszFullpathToFile, _In_ BOOL fComputeHash, _In_ PFILEINFO pFileInfo)
{
    SB_ASSERT(pszFullpathToFile);
    SB_ASSERT(pFileInfo);

    ZeroMemory(pFileInfo, sizeof(*pFileInfo));

    // Copy file/dir name over to the FILEINFO struct
    PCWSTR pszFilename = CHL_SzGetFilenameFromPath(pszFullpathToFile, wcslen(pszFullpathToFile));
    int nCharsInRoot = 0;
    for (const WCHAR* pch = pszFullpathToFile; pch != pszFilename; ++pch, ++nCharsInRoot)
        ;
    
    // Copy folder path first (we've calculate the length to copy)
    wcsncpy_s(pFileInfo->szPath, ARRAYSIZE(pFileInfo->szPath), pszFullpathToFile, nCharsInRoot);
    
    // Now copy the filename
    wcscpy_s(pFileInfo->szFilename, ARRAYSIZE(pFileInfo->szFilename), pszFilename);

    // Check if file is a directory
    // TODO: To extend this limit to 32,767 wide characters, 
    // call the Unicode version of the function and prepend "\\?\" to the path
    WIN32_FILE_ATTRIBUTE_DATA fileAttr;
    if(!GetFileAttributesEx(pszFullpathToFile, GetFileExInfoStandard, &fileAttr))
    {
        logerr(L"Unable to get attributes of file: %s", pszFullpathToFile);
        goto error_return;
    }

	// Store FILETIME in fileinfo for easy comparison in sorting the listview rows
	CopyMemory(&pFileInfo->ftModifiedTime, &fileAttr.ftLastWriteTime, sizeof(pFileInfo->ftModifiedTime));

	// Convert filetime to localtime and store in fileinfo
	SYSTEMTIME stUTC;
	FileTimeToSystemTime(&pFileInfo->ftModifiedTime, &stUTC);
	SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &pFileInfo->stModifiedTime);

    if(fileAttr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
    {
        pFileInfo->fIsDirectory = TRUE;
    }
    else
    {
		pFileInfo->llFilesize.HighPart = fileAttr.nFileSizeHigh;
		pFileInfo->llFilesize.LowPart = fileAttr.nFileSizeLow;

        if(fComputeHash)
        {
            // Generate hash. Open file handle first...    
            HANDLE hFile = CreateFileW(pszFullpathToFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
            if(hFile == INVALID_HANDLE_VALUE)
            {
                logerr(L"Failed to open file %s", pszFullpathToFile);
                goto error_return;
            }

            HRESULT hr = CalculateSHA1(g_hCrypt, hFile, pFileInfo->abHash);
            CloseHandle(hFile);
            if(FAILED(hr))
            {
                logerr(L"Failed to compute hash (0x%08x) for file: %s", hr, pszFullpathToFile);
                goto error_return;
            }
        }
    }
{'fraction_non_alphanumeric': 0.10736994219653179, 'fraction_numerical': 0.005491329479768786, 'mean_word_length': 2.737041036717063, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 30, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2837699', 'n_tokens_mistral': 2263, 'n_tokens_neox': 2183, 'n_words': 510}