Add utility functions needed for rect-based event targeting
[chromium-blink-merge.git] / tools / gn / path_output.cc
blob4e71f9bdc9810c77f4652ce38e440b90b0df4266
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 "build/build_config.h"
8 #include "tools/gn/filesystem_utils.h"
9 #include "tools/gn/output_file.h"
10 #include "tools/gn/string_utils.h"
12 PathOutput::PathOutput(const SourceDir& current_dir,
13 EscapingMode escaping,
14 bool convert_slashes)
15 : current_dir_(current_dir) {
16 CHECK(current_dir.is_source_absolute())
17 << "Currently this only supports writing to output directories inside "
18 "the source root. There needs to be some tweaks to PathOutput to make "
19 "doing this work correctly.";
20 inverse_current_dir_ = InvertDir(current_dir_);
22 options_.mode = escaping;
23 options_.convert_slashes = convert_slashes;
24 options_.inhibit_quoting = false;
26 if (convert_slashes)
27 ConvertPathToSystem(&inverse_current_dir_);
30 PathOutput::~PathOutput() {
33 void PathOutput::WriteFile(std::ostream& out, const SourceFile& file) const {
34 WritePathStr(out, file.value());
37 void PathOutput::WriteDir(std::ostream& out,
38 const SourceDir& dir,
39 DirSlashEnding slash_ending) const {
40 if (dir.value() == "/") {
41 // Writing system root is always a slash (this will normally only come up
42 // on Posix systems).
43 if (slash_ending == DIR_NO_LAST_SLASH)
44 out << "/.";
45 else
46 out << "/";
47 } else if (dir.value() == "//") {
48 // Writing out the source root.
49 if (slash_ending == DIR_NO_LAST_SLASH) {
50 // The inverse_current_dir_ will contain a [back]slash at the end, so we
51 // can't just write it out.
52 if (inverse_current_dir_.empty()) {
53 out << ".";
54 } else {
55 out.write(inverse_current_dir_.c_str(),
56 inverse_current_dir_.size() - 1);
58 } else {
59 if (inverse_current_dir_.empty())
60 out << "./";
61 else
62 out << inverse_current_dir_;
64 } else if (dir == current_dir_) {
65 // Writing the same directory. This needs special handling here since
66 // we need to output something else other than the input.
67 if (slash_ending == DIR_INCLUDE_LAST_SLASH)
68 out << "./";
69 else
70 out << ".";
71 } else if (slash_ending == DIR_INCLUDE_LAST_SLASH) {
72 WritePathStr(out, dir.value());
73 } else {
74 // DIR_NO_LAST_SLASH mode, just trim the last char.
75 WritePathStr(out, base::StringPiece(dir.value().data(),
76 dir.value().size() - 1));
80 void PathOutput::WriteFile(std::ostream& out, const OutputFile& file) const {
81 // Here we assume that the path is already preprocessed.
82 EscapeStringToStream(out, file.value(), options_);
85 void PathOutput::WriteFile(std::ostream& out,
86 const base::FilePath& file) const {
87 // Assume native file paths are always absolute.
88 EscapeStringToStream(out, FilePathToUTF8(file), options_);
91 void PathOutput::WriteSourceRelativeString(
92 std::ostream& out,
93 const base::StringPiece& str) const {
94 if (options_.mode == ESCAPE_SHELL) {
95 // Shell escaping needs an intermediate string since it may end up
96 // quoting the whole thing. On Windows, the slashes may already be
97 // converted to backslashes in inverse_current_dir_, but we assume that on
98 // Windows the escaper won't try to then escape the preconverted
99 // backslashes and will just pass them, so this is fine.
100 std::string intermediate;
101 intermediate.reserve(inverse_current_dir_.size() + str.size());
102 intermediate.assign(inverse_current_dir_.c_str(),
103 inverse_current_dir_.size());
104 intermediate.append(str.data(), str.size());
106 EscapeStringToStream(out,
107 base::StringPiece(intermediate.c_str(), intermediate.size()),
108 options_);
109 } else {
110 // Ninja (and none) escaping can avoid the intermediate string and
111 // reprocessing of the inverse_current_dir_.
112 out << inverse_current_dir_;
113 EscapeStringToStream(out, str, options_);
117 void PathOutput::WritePathStr(std::ostream& out,
118 const base::StringPiece& str) const {
119 DCHECK(str.size() > 0 && str[0] == '/');
121 if (str.substr(0, current_dir_.value().size()) ==
122 base::StringPiece(current_dir_.value())) {
123 // The current dir is a prefix of the output file, so we can strip the
124 // prefix and write out the result.
125 EscapeStringToStream(out, str.substr(current_dir_.value().size()),
126 options_);
127 } else if (str.size() >= 2 && str[1] == '/') {
128 WriteSourceRelativeString(out, str.substr(2));
129 } else {
130 // Input begins with one slash, don't write the current directory since
131 // it's system-absolute.
132 #if defined(OS_WIN)
133 // On Windows, trim the leading slash, since the input for absolute
134 // paths will look like "/C:/foo/bar.txt".
135 EscapeStringToStream(out, str.substr(1), options_);
136 #else
137 EscapeStringToStream(out, str, options_);
138 #endif