Remove ServiceDiscoveryClient* from PrivetHTTPAsynchronousFactoryImpl interface
[chromium-blink-merge.git] / tools / gn / source_dir.cc
blob8798b4d8dcc946191585f080f2e1213921a5a18e
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"
11 namespace {
13 void AssertValueSourceDirString(const std::string& s) {
14 if (!s.empty()) {
15 #if defined(OS_WIN)
16 DCHECK(s[0] == '/' ||
17 (s.size() > 2 && s[0] != '/' && s[1] == ':' && IsSlash(s[2])));
18 #else
19 DCHECK(s[0] == '/');
20 #endif
21 DCHECK(EndsWithSlash(s));
25 } // namespace
27 SourceDir::SourceDir() {
30 SourceDir::SourceDir(const base::StringPiece& p)
31 : value_(p.data(), p.size()) {
32 if (!EndsWithSlash(value_))
33 value_.push_back('/');
34 AssertValueSourceDirString(value_);
37 SourceDir::SourceDir(SwapIn, std::string* s) {
38 value_.swap(*s);
39 if (!EndsWithSlash(value_))
40 value_.push_back('/');
41 AssertValueSourceDirString(value_);
44 SourceDir::~SourceDir() {
47 SourceFile SourceDir::ResolveRelativeFile(
48 const base::StringPiece& p,
49 const base::StringPiece& source_root) const {
50 SourceFile ret;
52 DCHECK(source_root.empty() || !source_root.ends_with("/"));
54 // It's an error to resolve an empty string or one that is a directory
55 // (indicated by a trailing slash) because this is the function that expects
56 // to return a file.
57 if (p.empty() || (p.size() > 0 && p[p.size() - 1] == '/'))
58 return SourceFile();
59 if (p.size() >= 2 && p[0] == '/' && p[1] == '/') {
60 // Source-relative.
61 ret.value_.assign(p.data(), p.size());
62 NormalizePath(&ret.value_);
63 return ret;
64 } else if (IsPathAbsolute(p)) {
65 if (source_root.empty() ||
66 !MakeAbsolutePathRelativeIfPossible(source_root, p, &ret.value_)) {
67 #if defined(OS_WIN)
68 // On Windows we'll accept "C:\foo" as an absolute path, which we want
69 // to convert to "/C:..." here.
70 if (p[0] != '/')
71 ret.value_ = "/";
72 #endif
73 ret.value_.append(p.data(), p.size());
75 NormalizePath(&ret.value_);
76 return ret;
79 if (!source_root.empty()) {
80 std::string absolute =
81 FilePathToUTF8(Resolve(UTF8ToFilePath(source_root)).AppendASCII(
82 p.as_string()).value());
83 NormalizePath(&absolute);
84 if (!MakeAbsolutePathRelativeIfPossible(source_root, absolute,
85 &ret.value_)) {
86 #if defined(OS_WIN)
87 // On Windows we'll accept "C:\foo" as an absolute path, which we want
88 // to convert to "/C:..." here.
89 if (absolute[0] != '/')
90 ret.value_ = "/";
91 #endif
92 ret.value_.append(absolute.data(), absolute.size());
94 return ret;
97 // With no source_root_, there's nothing we can do about
98 // e.g. p=../../../path/to/file and value_=//source and we'll
99 // errornously return //file.
100 ret.value_.reserve(value_.size() + p.size());
101 ret.value_.assign(value_);
102 ret.value_.append(p.data(), p.size());
104 NormalizePath(&ret.value_);
105 return ret;
108 SourceDir SourceDir::ResolveRelativeDir(
109 const base::StringPiece& p,
110 const base::StringPiece& source_root) const {
111 SourceDir ret;
113 DCHECK(source_root.empty() || !source_root.ends_with("/"));
115 if (p.empty())
116 return ret;
117 if (p.size() >= 2 && p[0] == '/' && p[1] == '/') {
118 // Source-relative.
119 ret.value_.assign(p.data(), p.size());
120 if (!EndsWithSlash(ret.value_))
121 ret.value_.push_back('/');
122 NormalizePath(&ret.value_);
123 return ret;
124 } else if (IsPathAbsolute(p)) {
125 if (source_root.empty() ||
126 !MakeAbsolutePathRelativeIfPossible(source_root, p, &ret.value_)) {
127 #if defined(OS_WIN)
128 if (p[0] != '/') // See the file case for why we do this check.
129 ret.value_ = "/";
130 #endif
131 ret.value_.append(p.data(), p.size());
133 NormalizePath(&ret.value_);
134 if (!EndsWithSlash(ret.value_))
135 ret.value_.push_back('/');
136 return ret;
139 if (!source_root.empty()) {
140 std::string absolute =
141 FilePathToUTF8(Resolve(UTF8ToFilePath(source_root)).AppendASCII(
142 p.as_string()).value());
143 NormalizePath(&absolute);
144 if (!MakeAbsolutePathRelativeIfPossible(source_root, absolute,
145 &ret.value_)) {
146 #if defined(OS_WIN)
147 if (absolute[0] != '/') // See the file case for why we do this check.
148 ret.value_ = "/";
149 #endif
150 ret.value_.append(absolute.data(), absolute.size());
152 if (!EndsWithSlash(ret.value_))
153 ret.value_.push_back('/');
154 return ret;
157 ret.value_.reserve(value_.size() + p.size());
158 ret.value_.assign(value_);
159 ret.value_.append(p.data(), p.size());
161 NormalizePath(&ret.value_);
162 if (!EndsWithSlash(ret.value_))
163 ret.value_.push_back('/');
164 AssertValueSourceDirString(ret.value_);
166 return ret;
169 base::FilePath SourceDir::Resolve(const base::FilePath& source_root) const {
170 if (is_null())
171 return base::FilePath();
173 std::string converted;
174 if (is_system_absolute()) {
175 if (value_.size() > 2 && value_[2] == ':') {
176 // Windows path, strip the leading slash.
177 converted.assign(&value_[1], value_.size() - 1);
178 } else {
179 converted.assign(value_);
181 return base::FilePath(UTF8ToFilePath(converted));
184 // String the double-leading slash for source-relative paths.
185 converted.assign(&value_[2], value_.size() - 2);
186 return source_root.Append(UTF8ToFilePath(converted))
187 .NormalizePathSeparatorsTo('/');
190 void SourceDir::SwapValue(std::string* v) {
191 value_.swap(*v);
192 AssertValueSourceDirString(value_);