[Session restore] Rename group name Enabled to Restore.
[chromium-blink-merge.git] / tools / gn / path_output.cc
blob5b333d8a16f4284803f70a81d0bba8f06cb708a3
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/path_output.h"
7 #include "base/strings/string_util.h"
8 #include "build/build_config.h"
9 #include "tools/gn/filesystem_utils.h"
10 #include "tools/gn/output_file.h"
11 #include "tools/gn/string_utils.h"
13 PathOutput::PathOutput(const SourceDir& current_dir,
14 const base::StringPiece& source_root,
15 EscapingMode escaping)
16 : current_dir_(current_dir) {
17 inverse_current_dir_ = RebasePath("//", current_dir, source_root);
18 if (!EndsWithSlash(inverse_current_dir_))
19 inverse_current_dir_.push_back('/');
20 options_.mode = escaping;
23 PathOutput::~PathOutput() {
26 void PathOutput::WriteFile(std::ostream& out, const SourceFile& file) const {
27 WritePathStr(out, file.value());
30 void PathOutput::WriteDir(std::ostream& out,
31 const SourceDir& dir,
32 DirSlashEnding slash_ending) const {
33 if (dir.value() == "/") {
34 // Writing system root is always a slash (this will normally only come up
35 // on Posix systems).
36 if (slash_ending == DIR_NO_LAST_SLASH)
37 out << "/.";
38 else
39 out << "/";
40 } else if (dir.value() == "//") {
41 // Writing out the source root.
42 if (slash_ending == DIR_NO_LAST_SLASH) {
43 // The inverse_current_dir_ will contain a [back]slash at the end, so we
44 // can't just write it out.
45 if (inverse_current_dir_.empty()) {
46 out << ".";
47 } else {
48 out.write(inverse_current_dir_.c_str(),
49 inverse_current_dir_.size() - 1);
51 } else {
52 if (inverse_current_dir_.empty())
53 out << "./";
54 else
55 out << inverse_current_dir_;
57 } else if (dir == current_dir_) {
58 // Writing the same directory. This needs special handling here since
59 // we need to output something else other than the input.
60 if (slash_ending == DIR_INCLUDE_LAST_SLASH)
61 out << "./";
62 else
63 out << ".";
64 } else if (slash_ending == DIR_INCLUDE_LAST_SLASH) {
65 WritePathStr(out, dir.value());
66 } else {
67 // DIR_NO_LAST_SLASH mode, just trim the last char.
68 WritePathStr(out, base::StringPiece(dir.value().data(),
69 dir.value().size() - 1));
73 void PathOutput::WriteFile(std::ostream& out, const OutputFile& file) const {
74 // Here we assume that the path is already preprocessed.
75 EscapeStringToStream(out, file.value(), options_);
78 void PathOutput::WriteFiles(std::ostream& out,
79 const std::vector<OutputFile>& files) const {
80 for (const auto& file : files) {
81 out << " ";
82 WriteFile(out, file);
86 void PathOutput::WriteDir(std::ostream& out,
87 const OutputFile& file,
88 DirSlashEnding slash_ending) const {
89 DCHECK(file.value().empty() ||
90 file.value()[file.value().size() - 1] == '/');
92 switch (slash_ending) {
93 case DIR_INCLUDE_LAST_SLASH:
94 EscapeStringToStream(out, file.value(), options_);
95 break;
96 case DIR_NO_LAST_SLASH:
97 if (!file.value().empty() &&
98 file.value()[file.value().size() - 1] == '/') {
99 // Trim trailing slash.
100 EscapeStringToStream(
101 out,
102 base::StringPiece(file.value().data(), file.value().size() - 1),
103 options_);
104 } else {
105 // Doesn't end with a slash, write the whole thing.
106 EscapeStringToStream(out, file.value(), options_);
108 break;
112 void PathOutput::WriteFile(std::ostream& out,
113 const base::FilePath& file) const {
114 // Assume native file paths are always absolute.
115 EscapeStringToStream(out, FilePathToUTF8(file), options_);
118 void PathOutput::WriteSourceRelativeString(
119 std::ostream& out,
120 const base::StringPiece& str) const {
121 if (options_.mode == ESCAPE_NINJA_COMMAND) {
122 // Shell escaping needs an intermediate string since it may end up
123 // quoting the whole thing.
124 std::string intermediate;
125 intermediate.reserve(inverse_current_dir_.size() + str.size());
126 intermediate.assign(inverse_current_dir_.c_str(),
127 inverse_current_dir_.size());
128 intermediate.append(str.data(), str.size());
130 EscapeStringToStream(out,
131 base::StringPiece(intermediate.c_str(), intermediate.size()),
132 options_);
133 } else {
134 // Ninja (and none) escaping can avoid the intermediate string and
135 // reprocessing of the inverse_current_dir_.
136 out << inverse_current_dir_;
137 EscapeStringToStream(out, str, options_);
141 void PathOutput::WritePathStr(std::ostream& out,
142 const base::StringPiece& str) const {
143 DCHECK(str.size() > 0 && str[0] == '/');
145 if (str.substr(0, current_dir_.value().size()) ==
146 base::StringPiece(current_dir_.value())) {
147 // The current dir is a prefix of the output file, so we can strip the
148 // prefix and write out the result.
149 EscapeStringToStream(out, str.substr(current_dir_.value().size()),
150 options_);
151 } else if (str.size() >= 2 && str[1] == '/') {
152 WriteSourceRelativeString(out, str.substr(2));
153 } else {
154 // Input begins with one slash, don't write the current directory since
155 // it's system-absolute.
156 #if defined(OS_WIN)
157 // On Windows, trim the leading slash, since the input for absolute
158 // paths will look like "/C:/foo/bar.txt".
159 EscapeStringToStream(out, str.substr(1), options_);
160 #else
161 EscapeStringToStream(out, str, options_);
162 #endif