openMSX
win32-dirent.cc
Go to the documentation of this file.
1/* Copyright (C) 2001, 2006 Free Software Foundation, Inc.
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18// NB: Taken from http://www.koders.com/c/fidB38A2E97F60B8A0C903631F8C60078DE8C6C8433.aspx
19// Also modified to use Unicode calls explicitly
20// Slightly reformatted/simplified to fit openMSX coding style.
21
22#ifdef _WIN32
23
24#include "win32-dirent.hh"
25#include "utf8_checked.hh"
26#include "MSXException.hh"
27#include "xrange.hh"
28#include "zstring_view.hh"
29#include <windows.h>
30#include <cstring>
31#include <cstdlib>
32#include <exception>
33#include <iterator>
34
35namespace openmsx {
36
37DIR* opendir(const char* name)
38{
39 if (!name || !*name) return nullptr;
40
41 zstring_view name2 = name;
42 std::wstring nameW = utf8::utf8to16(name2);
43 if (!name2.ends_with('/') && !name2.ends_with("\\")) {
44 nameW += L"\\*";
45 } else {
46 nameW += L"*";
47 }
48
49 HANDLE hnd;
50 WIN32_FIND_DATAW find;
51 if ((hnd = FindFirstFileW(nameW.c_str(), &find)) == INVALID_HANDLE_VALUE) {
52 return nullptr;
53 }
54
55 auto* dir = new DIR;
56 dir->mask = nameW;
57 dir->fd = reinterpret_cast<INT_PTR>(hnd);
58 dir->data = new WIN32_FIND_DATAW;
59 dir->filepos = 0;
60 memcpy(dir->data, &find, sizeof(find));
61 return dir;
62}
63
64dirent* readdir(DIR* dir)
65{
66 static dirent entry;
67 entry.d_ino = 0;
68 entry.d_type = DT_UNKNOWN;
69
70 auto find = static_cast<WIN32_FIND_DATAW*>(dir->data);
71 if (dir->filepos) {
72 if (!FindNextFileW(reinterpret_cast<HANDLE>(dir->fd), find)) {
73 return nullptr;
74 }
75 }
76
77 std::string d_name = utf8::utf16to8(find->cFileName);
78 strncpy(entry.d_name, d_name.c_str(), std::size(entry.d_name));
79
80 entry.d_off = dir->filepos;
81 entry.d_reclen = static_cast<unsigned short>(strlen(entry.d_name));
82 dir->filepos++;
83 return &entry;
84}
85
86int closedir(DIR* dir)
87{
88 auto hnd = reinterpret_cast<HANDLE>(dir->fd);
89 delete static_cast<WIN32_FIND_DATAW*>(dir->data);
90 delete dir;
91 return FindClose(hnd) ? 0 : -1;
92}
93
94void rewinddir(DIR* dir)
95{
96 auto hnd = reinterpret_cast<HANDLE>(dir->fd);
97 auto find = static_cast<WIN32_FIND_DATAW*>(dir->data);
98
99 FindClose(hnd);
100 hnd = FindFirstFileW(dir->mask.c_str(), find);
101 dir->fd = reinterpret_cast<INT_PTR>(hnd);
102 dir->filepos = 0;
103}
104
105void seekdir(DIR* dir, off_t offset)
106{
107 rewinddir(dir);
108 repeat(offset, [&]{
109 if (FindNextFileW(reinterpret_cast<HANDLE>(dir->fd),
110 static_cast<WIN32_FIND_DATAW*>(dir->data))) {
111 dir->filepos++;
112 }
113 });
114}
115
116off_t telldir(DIR* dir)
117{
118 return dir->filepos;
119}
120
121// For correctness on 64-bit Windows, this function would need to maintain an
122// internal map of ints to HANDLEs, since HANDLEs are sizeof(void*). It's not
123// used at the moment in the openMSX sources, so let's not bother for now.
124/*int dirfd(DIR* dir)
125{
126 return dir->fd;
127}*/
128
129} // namespace openmsx
130
131#endif
Like std::string_view, but with the extra guarantee that it refers to a zero-terminated string.
constexpr bool ends_with(std::string_view sv) const
This file implemented 3 utility functions:
Definition Autofire.cc:11
auto find(InputRange &&range, const T &value)
Definition ranges.hh:162
u16bit_iterator utf8to16(octet_iterator start, octet_iterator end, u16bit_iterator result)
octet_iterator utf16to8(u16bit_iterator start, u16bit_iterator end, octet_iterator result)
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.
Definition xrange.hh:147