~ubuntu-branches/ubuntu/oneiric/mozc/oneiric

« back to all changes in this revision

Viewing changes to third_party/gtest/src/gtest-filepath.cc

  • Committer: Bazaar Package Importer
  • Author(s): Nobuhiro Iwamatsu
  • Date: 2010-07-14 03:26:47 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100714032647-13qjisj6m8cm8jdx
Tags: 0.12.410.102-1
* New upstream release (Closes: #588971).
  - Add mozc-server, mozc-utils-gui and scim-mozc packages.
* Update debian/rules.
  Add --gypdir option to build_mozc.py.
* Update debian/control.
  - Bumped standards-version to 3.9.0.
  - Update description.
* Add mozc icon (Closes: #588972).
* Add patch which revises issue 18.
  ibus_mozc_issue18.patch
* kFreeBSD build support.
  support_kfreebsd.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copyright 2008, Google Inc.
2
 
// All rights reserved.
3
 
//
4
 
// Redistribution and use in source and binary forms, with or without
5
 
// modification, are permitted provided that the following conditions are
6
 
// met:
7
 
//
8
 
//     * Redistributions of source code must retain the above copyright
9
 
// notice, this list of conditions and the following disclaimer.
10
 
//     * Redistributions in binary form must reproduce the above
11
 
// copyright notice, this list of conditions and the following disclaimer
12
 
// in the documentation and/or other materials provided with the
13
 
// distribution.
14
 
//     * Neither the name of Google Inc. nor the names of its
15
 
// contributors may be used to endorse or promote products derived from
16
 
// this software without specific prior written permission.
17
 
//
18
 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
 
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
 
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
 
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
 
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
 
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
 
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
 
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
 
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
 
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
 
//
30
 
// Authors: keith.ray@gmail.com (Keith Ray)
31
 
 
32
 
#include <gtest/internal/gtest-filepath.h>
33
 
#include <gtest/internal/gtest-port.h>
34
 
 
35
 
#include <stdlib.h>
36
 
 
37
 
#if GTEST_OS_WINDOWS_MOBILE
38
 
#include <windows.h>
39
 
#elif GTEST_OS_WINDOWS
40
 
#include <direct.h>
41
 
#include <io.h>
42
 
#elif GTEST_OS_SYMBIAN
43
 
// Symbian OpenC has PATH_MAX in sys/syslimits.h
44
 
#include <sys/syslimits.h>
45
 
#else
46
 
#include <limits.h>
47
 
#include <climits>  // Some Linux distributions define PATH_MAX here.
48
 
#endif  // GTEST_OS_WINDOWS_MOBILE
49
 
 
50
 
#if GTEST_OS_WINDOWS
51
 
#define GTEST_PATH_MAX_ _MAX_PATH
52
 
#elif defined(PATH_MAX)
53
 
#define GTEST_PATH_MAX_ PATH_MAX
54
 
#elif defined(_XOPEN_PATH_MAX)
55
 
#define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
56
 
#else
57
 
#define GTEST_PATH_MAX_ _POSIX_PATH_MAX
58
 
#endif  // GTEST_OS_WINDOWS
59
 
 
60
 
#include <gtest/internal/gtest-string.h>
61
 
 
62
 
namespace testing {
63
 
namespace internal {
64
 
 
65
 
#if GTEST_OS_WINDOWS
66
 
// On Windows, '\\' is the standard path separator, but many tools and the
67
 
// Windows API also accept '/' as an alternate path separator. Unless otherwise
68
 
// noted, a file path can contain either kind of path separators, or a mixture
69
 
// of them.
70
 
const char kPathSeparator = '\\';
71
 
const char kAlternatePathSeparator = '/';
72
 
const char kPathSeparatorString[] = "\\";
73
 
const char kAlternatePathSeparatorString[] = "/";
74
 
#if GTEST_OS_WINDOWS_MOBILE
75
 
// Windows CE doesn't have a current directory. You should not use
76
 
// the current directory in tests on Windows CE, but this at least
77
 
// provides a reasonable fallback.
78
 
const char kCurrentDirectoryString[] = "\\";
79
 
// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
80
 
const DWORD kInvalidFileAttributes = 0xffffffff;
81
 
#else
82
 
const char kCurrentDirectoryString[] = ".\\";
83
 
#endif  // GTEST_OS_WINDOWS_MOBILE
84
 
#else
85
 
const char kPathSeparator = '/';
86
 
const char kPathSeparatorString[] = "/";
87
 
const char kCurrentDirectoryString[] = "./";
88
 
#endif  // GTEST_OS_WINDOWS
89
 
 
90
 
// Returns whether the given character is a valid path separator.
91
 
static bool IsPathSeparator(char c) {
92
 
#if GTEST_HAS_ALT_PATH_SEP_
93
 
  return (c == kPathSeparator) || (c == kAlternatePathSeparator);
94
 
#else
95
 
  return c == kPathSeparator;
96
 
#endif
97
 
}
98
 
 
99
 
// Returns the current working directory, or "" if unsuccessful.
100
 
FilePath FilePath::GetCurrentDir() {
101
 
#if GTEST_OS_WINDOWS_MOBILE
102
 
  // Windows CE doesn't have a current directory, so we just return
103
 
  // something reasonable.
104
 
  return FilePath(kCurrentDirectoryString);
105
 
#elif GTEST_OS_WINDOWS
106
 
  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
107
 
  return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
108
 
#else
109
 
  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
110
 
  return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
111
 
#endif  // GTEST_OS_WINDOWS_MOBILE
112
 
}
113
 
 
114
 
// Returns a copy of the FilePath with the case-insensitive extension removed.
115
 
// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
116
 
// FilePath("dir/file"). If a case-insensitive extension is not
117
 
// found, returns a copy of the original FilePath.
118
 
FilePath FilePath::RemoveExtension(const char* extension) const {
119
 
  String dot_extension(String::Format(".%s", extension));
120
 
  if (pathname_.EndsWithCaseInsensitive(dot_extension.c_str())) {
121
 
    return FilePath(String(pathname_.c_str(), pathname_.length() - 4));
122
 
  }
123
 
  return *this;
124
 
}
125
 
 
126
 
// Returns a pointer to the last occurence of a valid path separator in
127
 
// the FilePath. On Windows, for example, both '/' and '\' are valid path
128
 
// separators. Returns NULL if no path separator was found.
129
 
const char* FilePath::FindLastPathSeparator() const {
130
 
  const char* const last_sep = strrchr(c_str(), kPathSeparator);
131
 
#if GTEST_HAS_ALT_PATH_SEP_
132
 
  const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
133
 
  // Comparing two pointers of which only one is NULL is undefined.
134
 
  if (last_alt_sep != NULL &&
135
 
      (last_sep == NULL || last_alt_sep > last_sep)) {
136
 
    return last_alt_sep;
137
 
  }
138
 
#endif
139
 
  return last_sep;
140
 
}
141
 
 
142
 
// Returns a copy of the FilePath with the directory part removed.
143
 
// Example: FilePath("path/to/file").RemoveDirectoryName() returns
144
 
// FilePath("file"). If there is no directory part ("just_a_file"), it returns
145
 
// the FilePath unmodified. If there is no file part ("just_a_dir/") it
146
 
// returns an empty FilePath ("").
147
 
// On Windows platform, '\' is the path separator, otherwise it is '/'.
148
 
FilePath FilePath::RemoveDirectoryName() const {
149
 
  const char* const last_sep = FindLastPathSeparator();
150
 
  return last_sep ? FilePath(String(last_sep + 1)) : *this;
151
 
}
152
 
 
153
 
// RemoveFileName returns the directory path with the filename removed.
154
 
// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
155
 
// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
156
 
// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
157
 
// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
158
 
// On Windows platform, '\' is the path separator, otherwise it is '/'.
159
 
FilePath FilePath::RemoveFileName() const {
160
 
  const char* const last_sep = FindLastPathSeparator();
161
 
  String dir;
162
 
  if (last_sep) {
163
 
    dir = String(c_str(), last_sep + 1 - c_str());
164
 
  } else {
165
 
    dir = kCurrentDirectoryString;
166
 
  }
167
 
  return FilePath(dir);
168
 
}
169
 
 
170
 
// Helper functions for naming files in a directory for xml output.
171
 
 
172
 
// Given directory = "dir", base_name = "test", number = 0,
173
 
// extension = "xml", returns "dir/test.xml". If number is greater
174
 
// than zero (e.g., 12), returns "dir/test_12.xml".
175
 
// On Windows platform, uses \ as the separator rather than /.
176
 
FilePath FilePath::MakeFileName(const FilePath& directory,
177
 
                                const FilePath& base_name,
178
 
                                int number,
179
 
                                const char* extension) {
180
 
  String file;
181
 
  if (number == 0) {
182
 
    file = String::Format("%s.%s", base_name.c_str(), extension);
183
 
  } else {
184
 
    file = String::Format("%s_%d.%s", base_name.c_str(), number, extension);
185
 
  }
186
 
  return ConcatPaths(directory, FilePath(file));
187
 
}
188
 
 
189
 
// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
190
 
// On Windows, uses \ as the separator rather than /.
191
 
FilePath FilePath::ConcatPaths(const FilePath& directory,
192
 
                               const FilePath& relative_path) {
193
 
  if (directory.IsEmpty())
194
 
    return relative_path;
195
 
  const FilePath dir(directory.RemoveTrailingPathSeparator());
196
 
  return FilePath(String::Format("%s%c%s", dir.c_str(), kPathSeparator,
197
 
                                 relative_path.c_str()));
198
 
}
199
 
 
200
 
// Returns true if pathname describes something findable in the file-system,
201
 
// either a file, directory, or whatever.
202
 
bool FilePath::FileOrDirectoryExists() const {
203
 
#if GTEST_OS_WINDOWS_MOBILE
204
 
  LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
205
 
  const DWORD attributes = GetFileAttributes(unicode);
206
 
  delete [] unicode;
207
 
  return attributes != kInvalidFileAttributes;
208
 
#else
209
 
  posix::StatStruct file_stat;
210
 
  return posix::Stat(pathname_.c_str(), &file_stat) == 0;
211
 
#endif  // GTEST_OS_WINDOWS_MOBILE
212
 
}
213
 
 
214
 
// Returns true if pathname describes a directory in the file-system
215
 
// that exists.
216
 
bool FilePath::DirectoryExists() const {
217
 
  bool result = false;
218
 
#if GTEST_OS_WINDOWS
219
 
  // Don't strip off trailing separator if path is a root directory on
220
 
  // Windows (like "C:\\").
221
 
  const FilePath& path(IsRootDirectory() ? *this :
222
 
                                           RemoveTrailingPathSeparator());
223
 
#else
224
 
  const FilePath& path(*this);
225
 
#endif
226
 
 
227
 
#if GTEST_OS_WINDOWS_MOBILE
228
 
  LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
229
 
  const DWORD attributes = GetFileAttributes(unicode);
230
 
  delete [] unicode;
231
 
  if ((attributes != kInvalidFileAttributes) &&
232
 
      (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
233
 
    result = true;
234
 
  }
235
 
#else
236
 
  posix::StatStruct file_stat;
237
 
  result = posix::Stat(path.c_str(), &file_stat) == 0 &&
238
 
      posix::IsDir(file_stat);
239
 
#endif  // GTEST_OS_WINDOWS_MOBILE
240
 
 
241
 
  return result;
242
 
}
243
 
 
244
 
// Returns true if pathname describes a root directory. (Windows has one
245
 
// root directory per disk drive.)
246
 
bool FilePath::IsRootDirectory() const {
247
 
#if GTEST_OS_WINDOWS
248
 
  // TODO(wan@google.com): on Windows a network share like
249
 
  // \\server\share can be a root directory, although it cannot be the
250
 
  // current directory.  Handle this properly.
251
 
  return pathname_.length() == 3 && IsAbsolutePath();
252
 
#else
253
 
  return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
254
 
#endif
255
 
}
256
 
 
257
 
// Returns true if pathname describes an absolute path.
258
 
bool FilePath::IsAbsolutePath() const {
259
 
  const char* const name = pathname_.c_str();
260
 
#if GTEST_OS_WINDOWS
261
 
  return pathname_.length() >= 3 &&
262
 
     ((name[0] >= 'a' && name[0] <= 'z') ||
263
 
      (name[0] >= 'A' && name[0] <= 'Z')) &&
264
 
     name[1] == ':' &&
265
 
     IsPathSeparator(name[2]);
266
 
#else
267
 
  return IsPathSeparator(name[0]);
268
 
#endif
269
 
}
270
 
 
271
 
// Returns a pathname for a file that does not currently exist. The pathname
272
 
// will be directory/base_name.extension or
273
 
// directory/base_name_<number>.extension if directory/base_name.extension
274
 
// already exists. The number will be incremented until a pathname is found
275
 
// that does not already exist.
276
 
// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
277
 
// There could be a race condition if two or more processes are calling this
278
 
// function at the same time -- they could both pick the same filename.
279
 
FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
280
 
                                          const FilePath& base_name,
281
 
                                          const char* extension) {
282
 
  FilePath full_pathname;
283
 
  int number = 0;
284
 
  do {
285
 
    full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
286
 
  } while (full_pathname.FileOrDirectoryExists());
287
 
  return full_pathname;
288
 
}
289
 
 
290
 
// Returns true if FilePath ends with a path separator, which indicates that
291
 
// it is intended to represent a directory. Returns false otherwise.
292
 
// This does NOT check that a directory (or file) actually exists.
293
 
bool FilePath::IsDirectory() const {
294
 
  return !pathname_.empty() &&
295
 
         IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
296
 
}
297
 
 
298
 
// Create directories so that path exists. Returns true if successful or if
299
 
// the directories already exist; returns false if unable to create directories
300
 
// for any reason.
301
 
bool FilePath::CreateDirectoriesRecursively() const {
302
 
  if (!this->IsDirectory()) {
303
 
    return false;
304
 
  }
305
 
 
306
 
  if (pathname_.length() == 0 || this->DirectoryExists()) {
307
 
    return true;
308
 
  }
309
 
 
310
 
  const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
311
 
  return parent.CreateDirectoriesRecursively() && this->CreateFolder();
312
 
}
313
 
 
314
 
// Create the directory so that path exists. Returns true if successful or
315
 
// if the directory already exists; returns false if unable to create the
316
 
// directory for any reason, including if the parent directory does not
317
 
// exist. Not named "CreateDirectory" because that's a macro on Windows.
318
 
bool FilePath::CreateFolder() const {
319
 
#if GTEST_OS_WINDOWS_MOBILE
320
 
  FilePath removed_sep(this->RemoveTrailingPathSeparator());
321
 
  LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
322
 
  int result = CreateDirectory(unicode, NULL) ? 0 : -1;
323
 
  delete [] unicode;
324
 
#elif GTEST_OS_WINDOWS
325
 
  int result = _mkdir(pathname_.c_str());
326
 
#else
327
 
  int result = mkdir(pathname_.c_str(), 0777);
328
 
#endif  // GTEST_OS_WINDOWS_MOBILE
329
 
 
330
 
  if (result == -1) {
331
 
    return this->DirectoryExists();  // An error is OK if the directory exists.
332
 
  }
333
 
  return true;  // No error.
334
 
}
335
 
 
336
 
// If input name has a trailing separator character, remove it and return the
337
 
// name, otherwise return the name string unmodified.
338
 
// On Windows platform, uses \ as the separator, other platforms use /.
339
 
FilePath FilePath::RemoveTrailingPathSeparator() const {
340
 
  return IsDirectory()
341
 
      ? FilePath(String(pathname_.c_str(), pathname_.length() - 1))
342
 
      : *this;
343
 
}
344
 
 
345
 
// Removes any redundant separators that might be in the pathname.
346
 
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
347
 
// redundancies that might be in a pathname involving "." or "..".
348
 
// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share).
349
 
void FilePath::Normalize() {
350
 
  if (pathname_.c_str() == NULL) {
351
 
    pathname_ = "";
352
 
    return;
353
 
  }
354
 
  const char* src = pathname_.c_str();
355
 
  char* const dest = new char[pathname_.length() + 1];
356
 
  char* dest_ptr = dest;
357
 
  memset(dest_ptr, 0, pathname_.length() + 1);
358
 
 
359
 
  while (*src != '\0') {
360
 
    *dest_ptr = *src;
361
 
    if (!IsPathSeparator(*src)) {
362
 
      src++;
363
 
    } else {
364
 
#if GTEST_HAS_ALT_PATH_SEP_
365
 
      if (*dest_ptr == kAlternatePathSeparator) {
366
 
        *dest_ptr = kPathSeparator;
367
 
      }
368
 
#endif
369
 
      while (IsPathSeparator(*src))
370
 
        src++;
371
 
    }
372
 
    dest_ptr++;
373
 
  }
374
 
  *dest_ptr = '\0';
375
 
  pathname_ = dest;
376
 
  delete[] dest;
377
 
}
378
 
 
379
 
}  // namespace internal
380
 
}  // namespace testing