// File: /workspace/github_c_makefile_star2_O2/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, %rbx
andq $0x0, 0x8(%rsp)
callq 0x3150
movq %rax, %r14
addq $-0x200, %rax           # imm = 0xFE00
cmpq $-0x202, %rax           # imm = 0xFDFE
ja 0xcae1
leaq 0x7fa9(%rip), %rsi      # 0x14a6c
pushq $0x2
popq %rdi
movq %rbx, %rdx
xorl %eax, %eax
addq $0x368, %rsp            # imm = 0x368
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x5981
leaq 0x50(%rsp), %rdi
movq %rbx, %rsi
callq 0x3320
movq %rbx, %rdi
callq 0x3500
testq %rax, %rax
je 0xcbd7
movq %rax, %r15
leaq 0x263(%rsp), %r12
leaq -0x1fe(%r14), %rax
movq %rax, 0x30(%rsp)
leaq (%rsp,%r14), %rax
addq $0x50, %rax
movq %rax, 0x18(%rsp)
leaq 0x51(%rsp,%r14), %rax
movq %rax, 0x10(%rsp)
leaq 0x250(%rsp), %rbp
leaq 0x8(%rsp), %rbx
leaq 0x38(%rsp), %r14
movq %r15, %rdi
movq %rbp, %rsi
movq %rbx, %rdx
callq 0x3100
testl %eax, %eax
jne 0xcbcd
cmpq $0x0, 0x8(%rsp)
je 0xcbcd
movq %r12, %rdi
callq 0x3150
movq %rax, %r13
movq %r12, %rdi
movq %rax, %rsi
callq 0xca04
testb %al, %al
jne 0xcb3f
addq 0x30(%rsp), %r13
cmpq $-0x201, %r13           # imm = 0xFDFF
ja 0xcb97
pushq $0x2
popq %rdi
leaq 0x7f08(%rip), %rsi      # 0x14a93
movq %r12, %rdx
xorl %eax, %eax
callq 0x5981
jmp 0xcb3f
movq 0x18(%rsp), %rax
movb $0x2f, (%rax)
movq 0x10(%rsp), %rdi
movq %r12, %rsi
callq 0x3320
movq %r14, %rdi
leaq 0x50(%rsp), %rsi
callq 0xc948
movq 0x20(%rsp), %rdi
movq %r14, %rsi
movq %r12, %rdx
callq *0x28(%rsp)
jmp 0xcb3f
movq %r15, %rdi
callq 0x3580
jmp 0xcbeb
leaq 0x7ea0(%rip), %rsi      # 0x14a7e
pushq $0x2
popq %rdi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x5981
addq $0x368, %rsp            # imm = 0x368
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nopl (%rax)