1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "tools/gn/source_dir.h"
7 #include "base/logging.h"
8 #include "tools/gn/filesystem_utils.h"
9 #include "tools/gn/source_file.h"
13 void AssertValueSourceDirString(const std::string
& s
) {
16 DCHECK(EndsWithSlash(s
));
22 SourceDir::SourceDir() {
25 SourceDir::SourceDir(const base::StringPiece
& p
)
26 : value_(p
.data(), p
.size()) {
27 if (!EndsWithSlash(value_
))
28 value_
.push_back('/');
29 AssertValueSourceDirString(value_
);
32 SourceDir::SourceDir(SwapIn
, std::string
* s
) {
34 if (!EndsWithSlash(value_
))
35 value_
.push_back('/');
36 AssertValueSourceDirString(value_
);
39 SourceDir::~SourceDir() {
42 SourceFile
SourceDir::ResolveRelativeFile(
43 const base::StringPiece
& p
,
44 const base::StringPiece
& source_root
) const {
47 // It's an error to resolve an empty string or one that is a directory
48 // (indicated by a trailing slash) because this is the function that expects
50 if (p
.empty() || (p
.size() > 0 && p
[p
.size() - 1] == '/'))
52 if (p
.size() >= 2 && p
[0] == '/' && p
[1] == '/') {
54 ret
.value_
.assign(p
.data(), p
.size());
55 NormalizePath(&ret
.value_
);
57 } else if (IsPathAbsolute(p
)) {
58 if (source_root
.empty() ||
59 !MakeAbsolutePathRelativeIfPossible(source_root
, p
, &ret
.value_
)) {
61 // On Windows we'll accept "C:\foo" as an absolute path, which we want
62 // to convert to "/C:..." here.
66 ret
.value_
.append(p
.data(), p
.size());
68 NormalizePath(&ret
.value_
);
72 ret
.value_
.reserve(value_
.size() + p
.size());
73 ret
.value_
.assign(value_
);
74 ret
.value_
.append(p
.data(), p
.size());
76 NormalizePath(&ret
.value_
);
80 SourceDir
SourceDir::ResolveRelativeDir(
81 const base::StringPiece
& p
,
82 const base::StringPiece
& source_root
) const {
87 if (p
.size() >= 2 && p
[0] == '/' && p
[1] == '/') {
89 ret
.value_
.assign(p
.data(), p
.size());
90 if (!EndsWithSlash(ret
.value_
))
91 ret
.value_
.push_back('/');
92 NormalizePath(&ret
.value_
);
94 } else if (IsPathAbsolute(p
)) {
95 if (source_root
.empty() ||
96 !MakeAbsolutePathRelativeIfPossible(source_root
, p
, &ret
.value_
)) {
98 if (p
[0] != '/') // See the file case for why we do this check.
101 ret
.value_
.append(p
.data(), p
.size());
103 NormalizePath(&ret
.value_
);
104 if (!EndsWithSlash(ret
.value_
))
105 ret
.value_
.push_back('/');
109 ret
.value_
.reserve(value_
.size() + p
.size());
110 ret
.value_
.assign(value_
);
111 ret
.value_
.append(p
.data(), p
.size());
113 NormalizePath(&ret
.value_
);
114 if (!EndsWithSlash(ret
.value_
))
115 ret
.value_
.push_back('/');
116 AssertValueSourceDirString(ret
.value_
);
121 base::FilePath
SourceDir::Resolve(const base::FilePath
& source_root
) const {
123 return base::FilePath();
125 std::string converted
;
126 if (is_system_absolute()) {
127 if (value_
.size() > 2 && value_
[2] == ':') {
128 // Windows path, strip the leading slash.
129 converted
.assign(&value_
[1], value_
.size() - 1);
131 converted
.assign(value_
);
133 return base::FilePath(UTF8ToFilePath(converted
));
136 // String the double-leading slash for source-relative paths.
137 converted
.assign(&value_
[2], value_
.size() - 2);
138 return source_root
.Append(UTF8ToFilePath(converted
))
139 .NormalizePathSeparatorsTo('/');
142 void SourceDir::SwapValue(std::string
* v
) {
144 AssertValueSourceDirString(value_
);