// File: /workspace/github_c_makefile_star2_O3/deplinenoise[P]tundra/src/FileInfo.cpp
// Function: t2::ListDirectory(char const*, void*, void (*)(void*, t2::FileInfo const&, char const*))
void ListDirectory(
    const char* path,
    void* user_data,
    void (*callback)(void* user_data, const FileInfo& info, const char* path))
{
#if defined(TUNDRA_UNIX)
	char full_fn[512];
	struct dirent entry;
	struct dirent* result = NULL;
	const size_t path_len = strlen(path);

	if (path_len + 1 > sizeof(full_fn)) {
    Log(kWarning, "path too long: %s", path);
		return;
  }

	strcpy(full_fn, path);

	DIR* dir = opendir(path);

	if (!dir)
  {
    Log(kWarning, "opendir() failed: %s", path);
		return;
  }

	while (0 == readdir_r(dir, &entry, &result) && result)
	{
    size_t len = strlen(entry.d_name);

    if (ShouldFilter(entry.d_name, len))
      continue;

		if (len + path_len + 2 >= sizeof(full_fn))
    {
			Log(kWarning, "%s: name too long\n", entry.d_name);
      continue;
    }

		full_fn[path_len] = '/';
		strcpy(full_fn + path_len + 1, entry.d_name);

    FileInfo info = GetFileInfo(full_fn);
    (*callback)(user_data, info, entry.d_name);
	}

	closedir(dir);

#else
	WIN32_FIND_DATAA find_data;
	char             scan_path[MAX_PATH];

	_snprintf(scan_path, sizeof(scan_path), "%s/*", path);

	for (int i = 0; i < MAX_PATH; ++i)
	{
		char ch = scan_path[i];
		if ('/' == ch)
			scan_path[i] = '\\';
		else if ('\0' == ch)
			break;
	}

	HANDLE h = FindFirstFileA(scan_path, &find_data);

	if (INVALID_HANDLE_VALUE == h)
  {
    Log(kWarning, "FindFirstFile() failed: %s", path);
		return;
  }

	do
	{
    if (ShouldFilter(find_data.cFileName, strlen(find_data.cFileName)))
      continue;

    static const uint64_t kEpochDiff = 0x019DB1DED53E8000LL; // 116444736000000000 nsecs
    static const uint64_t kRateDiff = 10000000; // 100 nsecs

    uint64_t ft = uint64_t(find_data.ftLastWriteTime.dwHighDateTime) << 32 | find_data.ftLastWriteTime.dwLowDateTime;

    FileInfo info;
    info.m_Flags     = FileInfo::kFlagExists;
    info.m_Size      = uint64_t(find_data.nFileSizeHigh) << 32 | find_data.nFileSizeLow;
    info.m_Timestamp = (ft - kEpochDiff) / kRateDiff;

    if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes)
      info.m_Flags |= FileInfo::kFlagDirectory;
    else
      info.m_Flags |= FileInfo::kFlagFile;

    (*callback)(user_data, info, find_data.cFileName);

	} while (FindNextFileA(h, &find_data));

	if (!FindClose(h))
		CroakErrno("couldn't close FindFile handle");
#endif
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x368, %rsp            # imm = 0x368
movq %rdx, 0x28(%rsp)
movq %rsi, 0x20(%rsp)
movq %rdi, %r12
movq $0x0, 0x8(%rsp)
callq 0x3150
movq %rax, %r13
addq $-0x200, %rax           # imm = 0xFE00
cmpq $-0x202, %rax           # imm = 0xFDFE
ja 0xd9ef
leaq 0x909f(%rip), %rsi      # 0x16a6e
movl $0x2, %edi
movq %r12, %rdx
xorl %eax, %eax
addq $0x368, %rsp            # imm = 0x368
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x5d74
leaq 0x160(%rsp), %rdi
movq %r12, %rsi
callq 0x3320
movq %r12, %rdi
callq 0x3500
testq %rax, %rax
je 0xdb0c
movq %rax, %r15
leaq 0x48(%rsp), %rsi
leaq 0x8(%rsp), %rdx
movq %rax, %rdi
callq 0x3100
testl %eax, %eax
jne 0xdb02
cmpq $0x0, 0x8(%rsp)
je 0xdb02
leaq 0x5b(%rsp), %r12
leaq -0x1fe(%r13), %r14
leaq (%rsp,%r13), %rax
addq $0x160, %rax            # imm = 0x160
movq %rax, 0x18(%rsp)
leaq (%rsp,%r13), %rax
addq $0x161, %rax            # imm = 0x161
movq %rax, 0x10(%rsp)
leaq 0x48(%rsp), %rbp
leaq 0x8(%rsp), %r13
movq %r12, %rdi
callq 0x3150
movq %rax, %rbx
movq %r12, %rdi
movq %rax, %rsi
callq 0xd91e
testb %al, %al
jne 0xdae4
addq %r14, %rbx
cmpq $-0x201, %rbx           # imm = 0xFDFF
ja 0xdaab
movl $0x2, %edi
leaq 0x8ff6(%rip), %rsi      # 0x16a95
movq %r12, %rdx
xorl %eax, %eax
callq 0x5d74
jmp 0xdae4
movq 0x18(%rsp), %rax
movb $0x2f, (%rax)
movq 0x10(%rsp), %rdi
movq %r12, %rsi
callq 0x3320
leaq 0x30(%rsp), %rbx
movq %rbx, %rdi
leaq 0x160(%rsp), %rsi
callq 0xd860
movq 0x20(%rsp), %rdi
movq %rbx, %rsi
movq %r12, %rdx
callq *0x28(%rsp)
movq %r15, %rdi
movq %rbp, %rsi
movq %r13, %rdx
callq 0x3100
testl %eax, %eax
jne 0xdb02
cmpq $0x0, 0x8(%rsp)
jne 0xda6d
movq %r15, %rdi
callq 0x3580
jmp 0xdb22
leaq 0x8f6d(%rip), %rsi      # 0x16a80
movl $0x2, %edi
movq %r12, %rdx
xorl %eax, %eax
callq 0x5d74
addq $0x368, %rsp            # imm = 0x368
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq