blob: b1f8ae00d3d197316acc140c2f42bfcd133bf733 [file] [log] [blame]
Michael J. Spencerdffde992010-11-29 22:28:51 +00001//===- llvm/Support/Win32/PathV2.cpp - Windows Path Impl --------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Windows specific implementation of the PathV2 API.
11//
12//===----------------------------------------------------------------------===//
13
14//===----------------------------------------------------------------------===//
15//=== WARNING: Implementation here must contain only generic Windows code that
16//=== is guaranteed to work on *all* Windows variants.
17//===----------------------------------------------------------------------===//
18
19#include "Windows.h"
20
Michael J. Spencerbee0c382010-12-01 19:32:01 +000021using namespace llvm;
22
23namespace {
24 error_code UTF8ToUTF16(const StringRef &utf8,
25 SmallVectorImpl<wchar_t> &utf16) {
26 int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
27 utf8.begin(), utf8.size(),
28 utf16.begin(), 0);
29
30 if (len == 0)
31 return make_error_code(windows_error(::GetLastError()));
32
33 utf16.reserve(len + 1);
34 utf16.set_size(len);
35
36 len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
37 utf8.begin(), utf8.size(),
38 utf16.begin(), utf16.size());
39
40 if (len == 0)
41 return make_error_code(windows_error(::GetLastError()));
42
43 // Make utf16 null terminated.
44 utf16.push_back(0);
45 utf16.pop_back();
46
47 return make_error_code(errc::success);
48 }
49}
50
Michael J. Spencerdffde992010-11-29 22:28:51 +000051namespace llvm {
52namespace sys {
53namespace path {
54
55error_code current_path(SmallVectorImpl<char> &result) {
56 SmallVector<wchar_t, 128> cur_path;
57 cur_path.reserve(128);
58retry_cur_dir:
59 DWORD len = ::GetCurrentDirectoryW(cur_path.capacity(), cur_path.data());
60
61 // A zero return value indicates a failure other than insufficient space.
62 if (len == 0)
63 return make_error_code(windows_error(::GetLastError()));
64
65 // If there's insufficient space, the len returned is larger than the len
66 // given.
67 if (len > cur_path.capacity()) {
68 cur_path.reserve(len);
69 goto retry_cur_dir;
70 }
71
72 cur_path.set_size(len);
73 // cur_path now holds the current directory in utf-16. Convert to utf-8.
74
75 // Find out how much space we need. Sadly, this function doesn't return the
76 // size needed unless you tell it the result size is 0, which means you
77 // _always_ have to call it twice.
78 len = ::WideCharToMultiByte(CP_UTF8, NULL,
79 cur_path.data(), cur_path.size(),
80 result.data(), 0,
81 NULL, NULL);
82
83 if (len == 0)
84 return make_error_code(windows_error(::GetLastError()));
85
86 result.reserve(len);
87 result.set_size(len);
88 // Now do the actual conversion.
89 len = ::WideCharToMultiByte(CP_UTF8, NULL,
90 cur_path.data(), cur_path.size(),
91 result.data(), result.size(),
92 NULL, NULL);
93 if (len == 0)
94 return make_error_code(windows_error(::GetLastError()));
95
96 return make_error_code(errc::success);
97}
98
99} // end namespace path
Michael J. Spencerbee0c382010-12-01 19:32:01 +0000100
101namespace fs {
102
103error_code copy_file(const Twine &from, const Twine &to, copy_option copt) {
104 // Get arguments.
105 SmallString<128> from_storage;
106 SmallString<128> to_storage;
Michael J. Spencer871498e2010-12-01 20:37:42 +0000107 StringRef f = from.toNullTerminatedStringRef(from_storage);
108 StringRef t = to.toNullTerminatedStringRef(to_storage);
Michael J. Spencerbee0c382010-12-01 19:32:01 +0000109
110 // Convert to utf-16.
111 SmallVector<wchar_t, 128> wide_from;
112 SmallVector<wchar_t, 128> wide_to;
113 if (error_code ec = UTF8ToUTF16(f, wide_from)) return ec;
114 if (error_code ec = UTF8ToUTF16(t, wide_to)) return ec;
115
116 // Copy the file.
117 BOOL res = ::CopyFileW(wide_from.begin(), wide_to.begin(),
118 copt != copy_option::overwrite_if_exists);
119
120 if (res == 0)
121 return make_error_code(windows_error(::GetLastError()));
122
123 return make_error_code(errc::success);
124}
125
126} // end namespace fs
Michael J. Spencerdffde992010-11-29 22:28:51 +0000127} // end namespace sys
128} // end namespace llvm