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 "StringOp.hh"
28 #include <windows.h>
29 #include <cstring>
30 #include <cstdlib>
31 #include <exception>
32 #include <iterator>
33 
34 namespace openmsx {
35 
36 DIR* opendir(const char* name)
37 {
38  if (!name || !*name) return nullptr;
39 
40  std::wstring nameW = utf8::utf8to16(name);
41  if (!StringOp::endsWith(name, '/') &&
42  !StringOp::endsWith(name, "\\")) {
43  nameW += L"\\*";
44  } else {
45  nameW += L"*";
46  }
47 
48  HANDLE hnd;
49  WIN32_FIND_DATAW find;
50  if ((hnd = FindFirstFileW(nameW.c_str(), &find)) == INVALID_HANDLE_VALUE) {
51  return nullptr;
52  }
53 
54  DIR* dir = new DIR;
55  dir->mask = nameW;
56  dir->fd = reinterpret_cast<INT_PTR>(hnd);
57  dir->data = new WIN32_FIND_DATAW;
58  dir->filepos = 0;
59  memcpy(dir->data, &find, sizeof(find));
60  return dir;
61 }
62 
63 dirent* readdir(DIR* dir)
64 {
65  static dirent entry;
66  entry.d_ino = 0;
67  entry.d_type = DT_UNKNOWN;
68 
69  auto find = static_cast<WIN32_FIND_DATAW*>(dir->data);
70  if (dir->filepos) {
71  if (!FindNextFileW(reinterpret_cast<HANDLE>(dir->fd), find)) {
72  return nullptr;
73  }
74  }
75 
76  std::string d_name = utf8::utf16to8(find->cFileName);
77  strncpy(entry.d_name, d_name.c_str(), std::size(entry.d_name));
78 
79  entry.d_off = dir->filepos;
80  entry.d_reclen = static_cast<unsigned short>(strlen(entry.d_name));
81  dir->filepos++;
82  return &entry;
83 }
84 
85 int closedir(DIR* dir)
86 {
87  auto hnd = reinterpret_cast<HANDLE>(dir->fd);
88  delete static_cast<WIN32_FIND_DATAW*>(dir->data);
89  delete dir;
90  return FindClose(hnd) ? 0 : -1;
91 }
92 
93 void rewinddir(DIR* dir)
94 {
95  auto hnd = reinterpret_cast<HANDLE>(dir->fd);
96  auto find = static_cast<WIN32_FIND_DATAW*>(dir->data);
97 
98  FindClose(hnd);
99  hnd = FindFirstFileW(dir->mask.c_str(), find);
100  dir->fd = reinterpret_cast<INT_PTR>(hnd);
101  dir->filepos = 0;
102 }
103 
104 void seekdir(DIR* dir, off_t offset)
105 {
106  rewinddir(dir);
107  for (off_t n = 0; n < offset; ++n) {
108  if (FindNextFileW(reinterpret_cast<HANDLE>(dir->fd),
109  static_cast<WIN32_FIND_DATAW*>(dir->data))) {
110  dir->filepos++;
111  }
112  }
113 }
114 
115 off_t telldir(DIR* dir)
116 {
117  return dir->filepos;
118 }
119 
120 // For correctness on 64-bit Windows, this function would need to maintain an
121 // internal map of ints to HANDLEs, since HANDLEs are sizeof(void*). It's not
122 // used at the moment in the openMSX sources, so let's not bother for now.
123 /*int dirfd(DIR* dir)
124 {
125  return dir->fd;
126 }*/
127 
128 } // namespace openmsx
129 
130 #endif
utf8::unchecked::size
size_t size(std::string_view utf8)
Definition: utf8_unchecked.hh:227
utf8::utf8to16
u16bit_iterator utf8to16(octet_iterator start, octet_iterator end, u16bit_iterator result)
Definition: utf8_checked.hh:227
MSXException.hh
openmsx::L
@ L
Definition: CPUCore.cc:204
StringOp::endsWith
bool endsWith(string_view total, string_view part)
Definition: StringOp.cc:81
ranges::find
auto find(InputRange &&range, const T &value)
Definition: ranges.hh:107
utf8_checked.hh
StringOp.hh
utf8::utf16to8
octet_iterator utf16to8(u16bit_iterator start, u16bit_iterator end, octet_iterator result)
Definition: utf8_checked.hh:204
win32-dirent.hh
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5