Directory.cxx 5.71 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 27

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

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

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

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

//----------------------------------------------------------------------------
47
unsigned long Directory::GetNumberOfFiles() const
48
{
Brad King's avatar
Brad King committed
49
  return static_cast<unsigned long>(this->Internal->Files.size());
50 51 52
}

//----------------------------------------------------------------------------
53
const char* Directory::GetFile(unsigned long dindex) const
54
{
55
  if (dindex >= this->Internal->Files.size()) {
56
    return 0;
57
  }
58 59 60
  return this->Internal->Files[dindex].c_str();
}

61 62 63 64 65 66
//----------------------------------------------------------------------------
const char* Directory::GetPath() const
{
  return this->Internal->Path.c_str();
}

67 68 69
//----------------------------------------------------------------------------
void Directory::Clear()
{
70
  this->Internal->Path.resize(0);
71 72 73
  this->Internal->Files.clear();
}

74 75
} // namespace KWSYS_NAMESPACE

76
// First Windows platforms
77

78
#if defined(_WIN32) && !defined(__CYGWIN__)
79
#include <windows.h>
80

81 82
#include <ctype.h>
#include <fcntl.h>
83
#include <io.h>
84 85 86 87 88 89
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

90 91
// Wide function names can vary depending on compiler:
#ifdef __BORLANDC__
92 93
#define _wfindfirst_func __wfindfirst
#define _wfindnext_func __wfindnext
94
#else
95 96
#define _wfindfirst_func _wfindfirst
#define _wfindnext_func _wfindnext
97 98
#endif

99
namespace KWSYS_NAMESPACE {
100

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

127
  // Now put them into the file array
128 129 130
  srchHandle =
    _wfindfirst_func((wchar_t*)Encoding::ToWide(buf).c_str(), &data);
  delete[] buf;
Mathieu Malaterre's avatar
Mathieu Malaterre committed
131

132
  if (srchHandle == -1) {
133
    return 0;
134
  }
Mathieu Malaterre's avatar
Mathieu Malaterre committed
135

136
  // Loop through names
137
  do {
138
    this->Internal->Files.push_back(Encoding::ToNarrow(data.name));
139
  } while (_wfindnext_func(srchHandle, &data) != -1);
140
  this->Internal->Path = name;
141 142 143
  return _findclose(srchHandle) != -1;
}

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

  // Now put them into the file array
164 165 166
  srchHandle =
    _wfindfirst_func((wchar_t*)Encoding::ToWide(buf).c_str(), &data);
  delete[] buf;
167

168
  if (srchHandle == -1) {
169
    return 0;
170
  }
171 172 173

  // Loop through names
  unsigned long count = 0;
174
  do {
175
    count++;
176
  } while (_wfindnext_func(srchHandle, &data) != -1);
177 178 179 180
  _findclose(srchHandle);
  return count;
}

181 182 183 184 185 186 187
} // namespace KWSYS_NAMESPACE

#else

// Now the POSIX style directory access

#include <sys/types.h>
188

189
#include <dirent.h>
190

191 192 193 194 195
// 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__)
196 197 198 199 200
#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
201
#else
202
#define kwsys_dirent dirent
203 204
#endif

205
namespace KWSYS_NAMESPACE {
206

Brad King's avatar
Brad King committed
207
bool Directory::Load(const std::string& name)
208
{
209
  this->Clear();
210

211
  DIR* dir = opendir(name.c_str());
212

213
  if (!dir) {
214
    return 0;
215
  }
216

217
  for (kwsys_dirent* d = readdir(dir); d; d = readdir(dir)) {
218
    this->Internal->Files.push_back(d->d_name);
219
  }
220
  this->Internal->Path = name;
221 222 223
  closedir(dir);
  return 1;
}
224

Brad King's avatar
Brad King committed
225
unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name)
226
{
227
  DIR* dir = opendir(name.c_str());
228

229
  if (!dir) {
230
    return 0;
231
  }
232

233
  unsigned long count = 0;
234
  for (kwsys_dirent* d = readdir(dir); d; d = readdir(dir)) {
235
    count++;
236
  }
237 238 239 240
  closedir(dir);
  return count;
}

241 242 243
} // namespace KWSYS_NAMESPACE

#endif