mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-24 14:26:09 +03:00
251 lines
8.2 KiB
C++
251 lines
8.2 KiB
C++
|
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
// found in the LICENSE file.
|
||
|
|
||
|
#include <stddef.h>
|
||
|
|
||
|
#include "tools/gn/err.h"
|
||
|
#include "tools/gn/filesystem_utils.h"
|
||
|
#include "tools/gn/functions.h"
|
||
|
#include "tools/gn/parse_tree.h"
|
||
|
#include "tools/gn/scope.h"
|
||
|
#include "tools/gn/value.h"
|
||
|
|
||
|
namespace functions {
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
// Corresponds to the various values of "what" in the function call.
|
||
|
enum What {
|
||
|
WHAT_FILE,
|
||
|
WHAT_NAME,
|
||
|
WHAT_EXTENSION,
|
||
|
WHAT_DIR,
|
||
|
WHAT_ABSPATH,
|
||
|
WHAT_GEN_DIR,
|
||
|
WHAT_OUT_DIR,
|
||
|
};
|
||
|
|
||
|
// Returns the directory containing the input (resolving it against the
|
||
|
// |current_dir|), regardless of whether the input is a directory or a file.
|
||
|
SourceDir DirForInput(const Settings* settings,
|
||
|
const SourceDir& current_dir,
|
||
|
const Value& input,
|
||
|
Err* err) {
|
||
|
// Input should already have been validated as a string.
|
||
|
const std::string& input_string = input.string_value();
|
||
|
|
||
|
if (!input_string.empty() && input_string[input_string.size() - 1] == '/') {
|
||
|
// Input is a directory.
|
||
|
return current_dir.ResolveRelativeDir(input, err,
|
||
|
settings->build_settings()->root_path_utf8());
|
||
|
}
|
||
|
|
||
|
// Input is a file.
|
||
|
return current_dir.ResolveRelativeFile(input, err,
|
||
|
settings->build_settings()->root_path_utf8()).GetDir();
|
||
|
}
|
||
|
|
||
|
std::string GetOnePathInfo(const Settings* settings,
|
||
|
const SourceDir& current_dir,
|
||
|
What what,
|
||
|
const Value& input,
|
||
|
Err* err) {
|
||
|
if (!input.VerifyTypeIs(Value::STRING, err))
|
||
|
return std::string();
|
||
|
const std::string& input_string = input.string_value();
|
||
|
if (input_string.empty()) {
|
||
|
*err = Err(input, "Calling get_path_info on an empty string.");
|
||
|
return std::string();
|
||
|
}
|
||
|
|
||
|
switch (what) {
|
||
|
case WHAT_FILE: {
|
||
|
return FindFilename(&input_string).as_string();
|
||
|
}
|
||
|
case WHAT_NAME: {
|
||
|
std::string file = FindFilename(&input_string).as_string();
|
||
|
size_t extension_offset = FindExtensionOffset(file);
|
||
|
if (extension_offset == std::string::npos)
|
||
|
return file;
|
||
|
// Trim extension and dot.
|
||
|
return file.substr(0, extension_offset - 1);
|
||
|
}
|
||
|
case WHAT_EXTENSION: {
|
||
|
return FindExtension(&input_string).as_string();
|
||
|
}
|
||
|
case WHAT_DIR: {
|
||
|
base::StringPiece dir_incl_slash = FindDir(&input_string);
|
||
|
if (dir_incl_slash.empty())
|
||
|
return std::string(".");
|
||
|
// Trim slash since this function doesn't return trailing slashes. The
|
||
|
// times we don't do this are if the result is "/" and "//" since those
|
||
|
// slashes can't be trimmed.
|
||
|
if (dir_incl_slash == "/")
|
||
|
return std::string("/.");
|
||
|
if (dir_incl_slash == "//")
|
||
|
return std::string("//.");
|
||
|
return dir_incl_slash.substr(0, dir_incl_slash.size() - 1).as_string();
|
||
|
}
|
||
|
case WHAT_GEN_DIR: {
|
||
|
return DirectoryWithNoLastSlash(GetSubBuildDirAsSourceDir(
|
||
|
BuildDirContext(settings),
|
||
|
DirForInput(settings, current_dir, input, err),
|
||
|
BuildDirType::GEN));
|
||
|
}
|
||
|
case WHAT_OUT_DIR: {
|
||
|
return DirectoryWithNoLastSlash(GetSubBuildDirAsSourceDir(
|
||
|
BuildDirContext(settings),
|
||
|
DirForInput(settings, current_dir, input, err),
|
||
|
BuildDirType::OBJ));
|
||
|
}
|
||
|
case WHAT_ABSPATH: {
|
||
|
bool as_dir =
|
||
|
!input_string.empty() && input_string[input_string.size() - 1] == '/';
|
||
|
|
||
|
return current_dir.ResolveRelativeAs(
|
||
|
!as_dir, input, err, settings->build_settings()->root_path_utf8(),
|
||
|
&input_string);
|
||
|
}
|
||
|
default:
|
||
|
NOTREACHED();
|
||
|
return std::string();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
const char kGetPathInfo[] = "get_path_info";
|
||
|
const char kGetPathInfo_HelpShort[] =
|
||
|
"get_path_info: Extract parts of a file or directory name.";
|
||
|
const char kGetPathInfo_Help[] =
|
||
|
R"(get_path_info: Extract parts of a file or directory name.
|
||
|
|
||
|
get_path_info(input, what)
|
||
|
|
||
|
The first argument is either a string representing a file or directory name,
|
||
|
or a list of such strings. If the input is a list the return value will be a
|
||
|
list containing the result of applying the rule to each item in the input.
|
||
|
|
||
|
Possible values for the "what" parameter
|
||
|
|
||
|
"file"
|
||
|
The substring after the last slash in the path, including the name and
|
||
|
extension. If the input ends in a slash, the empty string will be
|
||
|
returned.
|
||
|
"foo/bar.txt" => "bar.txt"
|
||
|
"bar.txt" => "bar.txt"
|
||
|
"foo/" => ""
|
||
|
"" => ""
|
||
|
|
||
|
"name"
|
||
|
The substring of the file name not including the extension.
|
||
|
"foo/bar.txt" => "bar"
|
||
|
"foo/bar" => "bar"
|
||
|
"foo/" => ""
|
||
|
|
||
|
"extension"
|
||
|
The substring following the last period following the last slash, or the
|
||
|
empty string if not found. The period is not included.
|
||
|
"foo/bar.txt" => "txt"
|
||
|
"foo/bar" => ""
|
||
|
|
||
|
"dir"
|
||
|
The directory portion of the name, not including the slash.
|
||
|
"foo/bar.txt" => "foo"
|
||
|
"//foo/bar" => "//foo"
|
||
|
"foo" => "."
|
||
|
|
||
|
The result will never end in a slash, so if the resulting is empty, the
|
||
|
system ("/") or source ("//") roots, a "." will be appended such that it
|
||
|
is always legal to append a slash and a filename and get a valid path.
|
||
|
|
||
|
"out_dir"
|
||
|
The output file directory corresponding to the path of the given file,
|
||
|
not including a trailing slash.
|
||
|
"//foo/bar/baz.txt" => "//out/Default/obj/foo/bar"
|
||
|
|
||
|
"gen_dir"
|
||
|
The generated file directory corresponding to the path of the given file,
|
||
|
not including a trailing slash.
|
||
|
"//foo/bar/baz.txt" => "//out/Default/gen/foo/bar"
|
||
|
|
||
|
"abspath"
|
||
|
The full absolute path name to the file or directory. It will be resolved
|
||
|
relative to the current directory, and then the source- absolute version
|
||
|
will be returned. If the input is system- absolute, the same input will
|
||
|
be returned.
|
||
|
"foo/bar.txt" => "//mydir/foo/bar.txt"
|
||
|
"foo/" => "//mydir/foo/"
|
||
|
"//foo/bar" => "//foo/bar" (already absolute)
|
||
|
"/usr/include" => "/usr/include" (already absolute)
|
||
|
|
||
|
If you want to make the path relative to another directory, or to be
|
||
|
system-absolute, see rebase_path().
|
||
|
|
||
|
Examples
|
||
|
sources = [ "foo.cc", "foo.h" ]
|
||
|
result = get_path_info(source, "abspath")
|
||
|
# result will be [ "//mydir/foo.cc", "//mydir/foo.h" ]
|
||
|
|
||
|
result = get_path_info("//foo/bar/baz.cc", "dir")
|
||
|
# result will be "//foo/bar"
|
||
|
|
||
|
# Extract the source-absolute directory name,
|
||
|
result = get_path_info(get_path_info(path, "dir"), "abspath"
|
||
|
)";
|
||
|
|
||
|
Value RunGetPathInfo(Scope* scope,
|
||
|
const FunctionCallNode* function,
|
||
|
const std::vector<Value>& args,
|
||
|
Err* err) {
|
||
|
if (args.size() != 2) {
|
||
|
*err = Err(function, "Expecting two arguments to get_path_info.");
|
||
|
return Value();
|
||
|
}
|
||
|
|
||
|
// Extract the "what".
|
||
|
if (!args[1].VerifyTypeIs(Value::STRING, err))
|
||
|
return Value();
|
||
|
What what;
|
||
|
if (args[1].string_value() == "file") {
|
||
|
what = WHAT_FILE;
|
||
|
} else if (args[1].string_value() == "name") {
|
||
|
what = WHAT_NAME;
|
||
|
} else if (args[1].string_value() == "extension") {
|
||
|
what = WHAT_EXTENSION;
|
||
|
} else if (args[1].string_value() == "dir") {
|
||
|
what = WHAT_DIR;
|
||
|
} else if (args[1].string_value() == "out_dir") {
|
||
|
what = WHAT_OUT_DIR;
|
||
|
} else if (args[1].string_value() == "gen_dir") {
|
||
|
what = WHAT_GEN_DIR;
|
||
|
} else if (args[1].string_value() == "abspath") {
|
||
|
what = WHAT_ABSPATH;
|
||
|
} else {
|
||
|
*err = Err(args[1], "Unknown value for 'what'.");
|
||
|
return Value();
|
||
|
}
|
||
|
|
||
|
const SourceDir& current_dir = scope->GetSourceDir();
|
||
|
if (args[0].type() == Value::STRING) {
|
||
|
return Value(function, GetOnePathInfo(scope->settings(), current_dir, what,
|
||
|
args[0], err));
|
||
|
} else if (args[0].type() == Value::LIST) {
|
||
|
const std::vector<Value>& input_list = args[0].list_value();
|
||
|
Value result(function, Value::LIST);
|
||
|
for (const auto& cur : input_list) {
|
||
|
result.list_value().push_back(Value(function,
|
||
|
GetOnePathInfo(scope->settings(), current_dir, what, cur, err)));
|
||
|
if (err->has_error())
|
||
|
return Value();
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
*err = Err(args[0], "Path must be a string or a list of strings.");
|
||
|
return Value();
|
||
|
}
|
||
|
|
||
|
} // namespace functions
|