Fix crash when using remote DevTools on CrOS WebUI - check for response_headers
[chromium-blink-merge.git] / tools / gn / function_get_path_info.cc
blob23f690cfdc096e2ef90eb011e16ded80316189b2
1 // Copyright 2014 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/err.h"
6 #include "tools/gn/filesystem_utils.h"
7 #include "tools/gn/functions.h"
8 #include "tools/gn/parse_tree.h"
9 #include "tools/gn/scope.h"
10 #include "tools/gn/value.h"
12 namespace functions {
14 namespace {
16 // Corresponds to the various values of "what" in the function call.
17 enum What {
18 WHAT_FILE,
19 WHAT_NAME,
20 WHAT_EXTENSION,
21 WHAT_DIR,
22 WHAT_ABSPATH,
25 std::string GetOnePathInfo(const SourceDir& current_dir,
26 What what,
27 const Value& input,
28 Err* err) {
29 if (!input.VerifyTypeIs(Value::STRING, err))
30 return std::string();
31 const std::string& input_string = input.string_value();
32 if (input_string.empty()) {
33 *err = Err(input, "Calling get_path_info on an empty string.");
34 return std::string();
37 switch (what) {
38 case WHAT_FILE: {
39 return FindFilename(&input_string).as_string();
41 case WHAT_NAME: {
42 std::string file = FindFilename(&input_string).as_string();
43 size_t extension_offset = FindExtensionOffset(file);
44 if (extension_offset == std::string::npos)
45 return file;
46 // Trim extension and dot.
47 return file.substr(0, extension_offset - 1);
49 case WHAT_EXTENSION: {
50 return FindExtension(&input_string).as_string();
52 case WHAT_DIR: {
53 base::StringPiece dir_incl_slash = FindDir(&input_string);
54 if (dir_incl_slash.empty())
55 return std::string(".");
56 // Trim slash since this function doesn't return trailing slashes. The
57 // times we don't do this are if the result is "/" and "//" since those
58 // slashes can't be trimmed.
59 if (dir_incl_slash == "/")
60 return std::string("/.");
61 if (dir_incl_slash == "//")
62 return std::string("//.");
63 return dir_incl_slash.substr(0, dir_incl_slash.size() - 1).as_string();
65 case WHAT_ABSPATH: {
66 if (!input_string.empty() && input_string[input_string.size() - 1] == '/')
67 return current_dir.ResolveRelativeDir(input_string).value();
68 else
69 return current_dir.ResolveRelativeFile(input_string).value();
71 default:
72 NOTREACHED();
73 return std::string();
77 } // namespace
79 const char kGetPathInfo[] = "get_path_info";
80 const char kGetPathInfo_HelpShort[] =
81 "get_path_info: Extract parts of a file or directory name.";
82 const char kGetPathInfo_Help[] =
83 "get_path_info: Extract parts of a file or directory name.\n"
84 "\n"
85 " get_path_info(input, what)\n"
86 "\n"
87 " The first argument is either a string representing a file or\n"
88 " directory name, or a list of such strings. If the input is a list\n"
89 " the return value will be a list containing the result of applying the\n"
90 " rule to each item in the input.\n"
91 "\n"
92 "Possible values for the \"what\" parameter\n"
93 "\n"
94 " \"file\"\n"
95 " The substring after the last slash in the path, including the name\n"
96 " and extension. If the input ends in a slash, the empty string will\n"
97 " be returned.\n"
98 " \"foo/bar.txt\" => \"bar.txt\"\n"
99 " \"bar.txt\" => \"bar.txt\"\n"
100 " \"foo/\" => \"\"\n"
101 " \"\" => \"\"\n"
102 "\n"
103 " \"name\"\n"
104 " The substring of the file name not including the extension.\n"
105 " \"foo/bar.txt\" => \"bar\"\n"
106 " \"foo/bar\" => \"bar\"\n"
107 " \"foo/\" => \"\"\n"
108 "\n"
109 " \"extension\"\n"
110 " The substring following the last period following the last slash,\n"
111 " or the empty string if not found. The period is not included.\n"
112 " \"foo/bar.txt\" => \"txt\"\n"
113 " \"foo/bar\" => \"\"\n"
114 "\n"
115 " \"dir\"\n"
116 " The directory portion of the name, not including the slash.\n"
117 " \"foo/bar.txt\" => \"foo\"\n"
118 " \"//foo/bar\" => \"//foo\"\n"
119 " \"foo\" => \".\"\n"
120 "\n"
121 " The result will never end in a slash, so if the resulting\n"
122 " is empty, the system (\"/\") or source (\"//\") roots, a \".\"\n"
123 " will be appended such that it is always legal to append a slash\n"
124 " and a filename and get a valid path.\n"
125 "\n"
126 " \"abspath\"\n"
127 " The full absolute path name to the file or directory. It will be\n"
128 " resolved relative to the currebt directory, and then the source-\n"
129 " absolute version will be returned. If the input is system-\n"
130 " absolute, the same input will be returned.\n"
131 " \"foo/bar.txt\" => \"//mydir/foo/bar.txt\"\n"
132 " \"foo/\" => \"//mydir/foo/\"\n"
133 " \"//foo/bar\" => \"//foo/bar\" (already absolute)\n"
134 " \"/usr/include\" => \"/usr/include\" (already absolute)\n"
135 "\n"
136 " If you want to make the path relative to another directory, or to\n"
137 " be system-absolute, see rebase_path().\n"
138 "\n"
139 "Examples\n"
140 " sources = [ \"foo.cc\", \"foo.h\" ]\n"
141 " result = get_path_info(source, \"abspath\")\n"
142 " # result will be [ \"//mydir/foo.cc\", \"//mydir/foo.h\" ]\n"
143 "\n"
144 " result = get_path_info(\"//foo/bar/baz.cc\", \"dir\")\n"
145 " # result will be \"//foo/bar\"\n"
146 "\n"
147 " # Extract the source-absolute directory name,\n"
148 " result = get_path_info(get_path_info(path, \"dir\"), \"abspath\")\n";
150 Value RunGetPathInfo(Scope* scope,
151 const FunctionCallNode* function,
152 const std::vector<Value>& args,
153 Err* err) {
154 if (args.size() != 2) {
155 *err = Err(function, "Expecting two arguments to get_path_info.");
156 return Value();
159 // Extract the "what".
160 if (!args[1].VerifyTypeIs(Value::STRING, err))
161 return Value();
162 What what;
163 if (args[1].string_value() == "file") {
164 what = WHAT_FILE;
165 } else if (args[1].string_value() == "name") {
166 what = WHAT_NAME;
167 } else if (args[1].string_value() == "extension") {
168 what = WHAT_EXTENSION;
169 } else if (args[1].string_value() == "dir") {
170 what = WHAT_DIR;
171 } else if (args[1].string_value() == "abspath") {
172 what = WHAT_ABSPATH;
173 } else {
174 *err = Err(args[1], "Unknown value for 'what'.");
175 return Value();
178 const SourceDir& current_dir = scope->GetSourceDir();
179 if (args[0].type() == Value::STRING) {
180 return Value(function, GetOnePathInfo(current_dir, what, args[0], err));
181 } else if (args[0].type() == Value::LIST) {
182 const std::vector<Value>& input_list = args[0].list_value();
183 Value result(function, Value::LIST);
184 for (size_t i = 0; i < input_list.size(); i++) {
185 result.list_value().push_back(Value(function,
186 GetOnePathInfo(current_dir, what, input_list[i], err)));
187 if (err->has_error())
188 return Value();
190 return result;
193 *err = Err(args[0], "Path must be a string or a list of strings.");
194 return Value();
197 } // namespace functions