Directory.cxx 5.21 KB
Newer Older
1 2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */
3 4
#include "kwsysPrivate.h"
#include KWSYS_HEADER(Directory.hxx)
5

6
#include KWSYS_HEADER(Configure.hxx)
Brad King's avatar
Brad King committed
7

8 9
#include KWSYS_HEADER(Encoding.hxx)

10 11 12
// Work-around CMake dependency scanning limitation.  This must
// duplicate the above list of headers.
#if 0
13 14 15
#include "Configure.hxx.in"
#include "Directory.hxx.in"
#include "Encoding.hxx.in"
16 17
#endif

Brad King's avatar
Brad King committed
18 19 20
#include <string>
#include <vector>

21
namespace KWSYS_NAMESPACE {
22 23 24 25 26

class DirectoryInternals
{
public:
  // Array of Files
Brad King's avatar
Brad King committed
27
  std::vector<std::string> Files;
Mathieu Malaterre's avatar
Mathieu Malaterre committed
28

29
  // Path to Open'ed directory
Brad King's avatar
Brad King committed
30
  std::string Path;
31 32 33 34 35 36 37 38 39 40 41 42
};

Directory::Directory()
{
  this->Internal = new DirectoryInternals;
}

Directory::~Directory()
{
  delete this->Internal;
}

43
unsigned long Directory::GetNumberOfFiles() const
44
{
Brad King's avatar
Brad King committed
45
  return static_cast<unsigned long>(this->Internal->Files.size());
46 47
}

48
const char* Directory::GetFile(unsigned long dindex) const
49
{
50
  if (dindex >= this->Internal->Files.size()) {
51
    return KWSYS_NULLPTR;
52
  }
53 54 55
  return this->Internal->Files[dindex].c_str();
}

56 57 58 59 60
const char* Directory::GetPath() const
{
  return this->Internal->Path.c_str();
}

61 62
void Directory::Clear()
{
63
  this->Internal->Path.resize(0);
64 65 66
  this->Internal->Files.clear();
}

67 68
} // namespace KWSYS_NAMESPACE

69
// First Windows platforms
70

71
#if defined(_WIN32) && !defined(__CYGWIN__)
72
#include <windows.h>
73

74 75
#include <ctype.h>
#include <fcntl.h>
76
#include <io.h>
77 78 79 80 81 82
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

83 84
// Wide function names can vary depending on compiler:
#ifdef __BORLANDC__
85 86
#define _wfindfirst_func __wfindfirst
#define _wfindnext_func __wfindnext
87
#else
88 89
#define _wfindfirst_func _wfindfirst
#define _wfindnext_func _wfindnext
90 91
#endif

92
namespace KWSYS_NAMESPACE {
93

Brad King's avatar
Brad King committed
94
bool Directory::Load(const std::string& name)
95
{
96
  this->Clear();
97 98
#if (defined(_MSC_VER) && _MSC_VER < 1300) || defined(__BORLANDC__)
  // Older Visual C++ and Embarcadero compilers.
99
  long srchHandle;
100
#else // Newer Visual C++
101 102
  intptr_t srchHandle;
#endif
103
  char* buf;
104
  size_t n = name.size();
105
  if (*name.rbegin() == '/' || *name.rbegin() == '\\') {
106
    buf = new char[n + 1 + 1];
107
    sprintf(buf, "%s*", name.c_str());
108
  } else {
109 110
    // Make sure the slashes in the wildcard suffix are consistent with the
    // rest of the path
111
    buf = new char[n + 2 + 1];
112
    if (name.find('\\') != std::string::npos) {
113
      sprintf(buf, "%s\\*", name.c_str());
114
    } else {
115
      sprintf(buf, "%s/*", name.c_str());
116
    }
117 118
  }
  struct _wfinddata_t data; // data of current file
Mathieu Malaterre's avatar
Mathieu Malaterre committed
119

120
  // Now put them into the file array
121 122
  srchHandle = _wfindfirst_func(
    (wchar_t*)Encoding::ToWindowsExtendedPath(buf).c_str(), &data);
123
  delete[] buf;
Mathieu Malaterre's avatar
Mathieu Malaterre committed
124

125
  if (srchHandle == -1) {
126
    return 0;
127
  }
Mathieu Malaterre's avatar
Mathieu Malaterre committed
128

129
  // Loop through names
130
  do {
131
    this->Internal->Files.push_back(Encoding::ToNarrow(data.name));
132
  } while (_wfindnext_func(srchHandle, &data) != -1);
133
  this->Internal->Path = name;
134 135 136
  return _findclose(srchHandle) != -1;
}

Brad King's avatar
Brad King committed
137
unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name)
138
{
139 140
#if (defined(_MSC_VER) && _MSC_VER < 1300) || defined(__BORLANDC__)
  // Older Visual C++ and Embarcadero compilers.
141
  long srchHandle;
142
#else // Newer Visual C++
143 144 145
  intptr_t srchHandle;
#endif
  char* buf;
146
  size_t n = name.size();
147
  if (*name.rbegin() == '/') {
148
    buf = new char[n + 1 + 1];
149
    sprintf(buf, "%s*", name.c_str());
150
  } else {
151
    buf = new char[n + 2 + 1];
152
    sprintf(buf, "%s/*", name.c_str());
153 154
  }
  struct _wfinddata_t data; // data of current file
155 156

  // Now put them into the file array
157 158 159
  srchHandle =
    _wfindfirst_func((wchar_t*)Encoding::ToWide(buf).c_str(), &data);
  delete[] buf;
160

161
  if (srchHandle == -1) {
162
    return 0;
163
  }
164 165 166

  // Loop through names
  unsigned long count = 0;
167
  do {
168
    count++;
169
  } while (_wfindnext_func(srchHandle, &data) != -1);
170 171 172 173
  _findclose(srchHandle);
  return count;
}

174 175 176 177 178 179 180
} // namespace KWSYS_NAMESPACE

#else

// Now the POSIX style directory access

#include <sys/types.h>
181

182
#include <dirent.h>
183

184 185 186 187 188
// PGI with glibc has trouble with dirent and large file support:
//  http://www.pgroup.com/userforum/viewtopic.php?
//  p=1992&sid=f16167f51964f1a68fe5041b8eb213b6
// Work around the problem by mapping dirent the same way as readdir.
#if defined(__PGI) && defined(__GLIBC__)
189 190 191 192 193
#define kwsys_dirent_readdir dirent
#define kwsys_dirent_readdir64 dirent64
#define kwsys_dirent kwsys_dirent_lookup(readdir)
#define kwsys_dirent_lookup(x) kwsys_dirent_lookup_delay(x)
#define kwsys_dirent_lookup_delay(x) kwsys_dirent_##x
194
#else
195
#define kwsys_dirent dirent
196 197
#endif

198
namespace KWSYS_NAMESPACE {
199

Brad King's avatar
Brad King committed
200
bool Directory::Load(const std::string& name)
201
{
202
  this->Clear();
203

204
  DIR* dir = opendir(name.c_str());
205

206
  if (!dir) {
207
    return 0;
208
  }
209

210
  for (kwsys_dirent* d = readdir(dir); d; d = readdir(dir)) {
211
    this->Internal->Files.push_back(d->d_name);
212
  }
213
  this->Internal->Path = name;
214 215 216
  closedir(dir);
  return 1;
}
217

Brad King's avatar
Brad King committed
218
unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name)
219
{
220
  DIR* dir = opendir(name.c_str());
221

222
  if (!dir) {
223
    return 0;
224
  }
225

226
  unsigned long count = 0;
227
  for (kwsys_dirent* d = readdir(dir); d; d = readdir(dir)) {
228
    count++;
229
  }
230 231 232 233
  closedir(dir);
  return count;
}

234 235 236
} // namespace KWSYS_NAMESPACE

#endif