<commit_before>//
// Copyright (c) 2009, <NAME>
// This software licensed under terms described in LICENSE.txt
//

#include "../platform.h"

#ifdef TINFRA_W32

#include "tinfra/fs.h"

#include "tinfra/win32.h"
#include "tinfra/path.h"
#include "tinfra/fmt.h"
#include "tinfra/cmd.h" // for getapp

#include <string>
#include <cctype>
#include <stdio.h>
#include <windows.h>

#include "tinfra/trace.h"

namespace tinfra {
namespace fs { 

tinfra::module_tracer win32_fs_tracer(tinfra::tinfra_tracer, "win32_fs", 70);

struct lister::internal_data {
    
    HANDLE ff_handle;
    WIN32_FIND_DATAW ff_data;
    bool         is_first;
    std::string  name_holder;
};

lister::lister(tstring const& path, bool /*need_stat*/)
    : data_(new internal_data())
{   
    TINFRA_TRACE(win32_fs_tracer, "lister::lister");    
    TINFRA_TRACE_VAR(win32_fs_tracer, path);
    std::wstring wname = tinfra::win32::make_wstring_from_utf8(path);
    wname.append(L"\\*.*");
    data_->ff_handle = FindFirstFileW(wname.c_str(), &data_->ff_data );
    
    if( data_->ff_handle == INVALID_HANDLE_VALUE ) {
        tinfra::win32::throw_system_error(fmt("unable to list directory '%s'") % path);
    }
    data_->is_first = true;
}
lister::~lister()
{
    TINFRA_TRACE(win32_fs_tracer, "lister::~lister");
    if( data_->ff_handle != INVALID_HANDLE_VALUE )
        FindClose(data_->ff_handle);
}

bool lister::fetch_next(directory_entry& result)
{
    TINFRA_TRACE(win32_fs_tracer, "lister::fetch_next");
    
    while( true ) {
        bool have_data = data_->is_first;
        data_->is_first = false;
        if( !have_data )
            have_data =  (FindNextFileW(data_->ff_handle, &data_->ff_data) != 0 );
        if( !have_data )
            return false;       
        
        WIN32_FIND_DATAW& ff_data = data_->ff_data;
        if( ff_data.cFileName[0] == '.' ) 
        {
            if( (ff_data.cFileName[1] == 0) ||
                (ff_data.cFileName[1] == '.' && ff_data.cFileName[2] == 0) )
            {
                continue;
            }
        }
        
        data_->name_holder = tinfra::win32::make_utf8(ff_data.cFileName);
        
        result.name = data_->name_holder;
        TINFRA_TRACE_VAR(win32_fs_tracer, result.name);
        result.info.is_dir = (ff_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == FILE_ATTRIBUTE_DIRECTORY;
        result.info.size = size_t(ff_data.nFileSizeLow);
        // TODO: add support for win64 build
        // result.info.size |= (size_t(ff_data.nFileSizeHigh) << 32);
        
        // TODO, recognize how to use FILETIME and how to convert it into timestamp
        result.info.modification_time = 0;
        result.info.access_time = 0;
        data_->is_first = false;
        return true;
    }
}

file_info stat(tstring const& name)
{
    const std::wstring w_name = tinfra::win32::make_wstring_from_utf8(name);
    
    WIN32_FILE_ATTRIBUTE_DATA file_attrs;
    <commit_msg>w32 fs::lister now correctly fills directory_entry.info.type field<commit_after>//
// Copyright (c) 2009, <NAME>
// This software licensed under terms described in LICENSE.txt
//

#include "../platform.h"

#ifdef TINFRA_W32

#include "tinfra/fs.h"

#include "tinfra/win32.h"
#include "tinfra/path.h"
#include "tinfra/fmt.h"
#include "tinfra/cmd.h" // for getapp

#include <string>
#include <cctype>
#include <stdio.h>
#include <windows.h>

#include "tinfra/trace.h"

namespace tinfra {
namespace fs { 

tinfra::module_tracer win32_fs_tracer(tinfra::tinfra_tracer, "win32_fs", 70);

struct lister::internal_data {
    
    HANDLE ff_handle;
    WIN32_FIND_DATAW ff_data;
    bool         is_first;
    std::string  name_holder;
};

lister::lister(tstring const& path, bool /*need_stat*/)
    : data_(new internal_data())
{   
    TINFRA_TRACE(win32_fs_tracer, "lister::lister");    
    TINFRA_TRACE_VAR(win32_fs_tracer, path);
    std::wstring wname = tinfra::win32::make_wstring_from_utf8(path);
    wname.append(L"\\*.*");
    data_->ff_handle = FindFirstFileW(wname.c_str(), &data_->ff_data );
    
    if( data_->ff_handle == INVALID_HANDLE_VALUE ) {
        tinfra::win32::throw_system_error(fmt("unable to list directory '%s'") % path);
    }
    data_->is_first = true;
}
lister::~lister()
{
    TINFRA_TRACE(win32_fs_tracer, "lister::~lister");
    if( data_->ff_handle != INVALID_HANDLE_VALUE )
        FindClose(data_->ff_handle);
}

bool lister::fetch_next(directory_entry& result)
{
    TINFRA_TRACE(win32_fs_tracer, "lister::fetch_next");
    
    while( true ) {
        bool have_data = data_->is_first;
        data_->is_first = false;
        if( !have_data )
            have_data =  (FindNextFileW(data_->ff_handle, &data_->ff_data) != 0 );
        if( !have_data )
            return false;       
        
        WIN32_FIND_DATAW& ff_data = data_->ff_data;
        if( ff_data.cFileName[0] == '.' ) 
        {
            if( (ff_data.cFileName[1] == 0) ||
                (ff_data.cFileName[1] == '.' && ff_data.cFileName[2] == 0) )
            {
                continue;
            }
        }
        
        data_->name_holder = tinfra::win32::make_utf8(ff_data.cFileName);
        
        result.name = data_->name_holder;
        TINFRA_TRACE_VAR(win32_fs_tracer, result.name);
        result.info.is_dir = (ff_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == FILE_ATTRIBUTE_DIRECTORY;
        result.info.type = result.info.is_dir ? DIRECTORY : REGULAR_FILE;
        result.info.size = size_t(ff_data.nFileSizeLow);
        // TODO: add support for win64 build
        // result.info.size |= (size_t(ff_data.nFileSizeHigh) << 32);
        
        // TODO, recognize how to use FILETIME and how to convert it into timestamp
        result.info.modification_time = 0;
        result.info.access_time = 0;
        data_->is_first = false;
        return true;
    }
}

file_info stat(tstring const& name)
{
    const std::wstring w_name = tinfra::win32::make_wstring_from_utf8(name);
    
    WIN32_FILE_ATTRIBUTE_DATA file_attrs;
    
{'fraction_non_alphanumeric': 0.13300083125519535, 'fraction_numerical': 0.01828761429758936, 'mean_word_length': 2.831847133757962, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 41, 'https://': 0, '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': '627133', 'n_tokens_mistral': 2238, 'n_tokens_neox': 2128, 'n_words': 368}