• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "gn/source_dir.h"
6 
7 #include <string>
8 
9 #include "base/logging.h"
10 #include "gn/filesystem_utils.h"
11 #include "gn/source_file.h"
12 #include "util/build_config.h"
13 
14 namespace {
15 
AssertValueSourceDirString(const std::string & s)16 void AssertValueSourceDirString(const std::string& s) {
17   if (!s.empty()) {
18 #if defined(OS_WIN)
19     DCHECK(s[0] == '/' ||
20            (s.size() > 2 && s[0] != '/' && s[1] == ':' && IsSlash(s[2])));
21 #else
22     DCHECK(s[0] == '/');
23 #endif
24     DCHECK(EndsWithSlash(s)) << s;
25   }
26 }
27 
28 // Validates input value (input_value) and sets proper error message.
29 // Note: Parameter blame_input is used only for generating error message.
30 template <typename StringType>
ValidateResolveInput(bool as_file,const Value & blame_input_value,const StringType & input_value,Err * err)31 bool ValidateResolveInput(bool as_file,
32                           const Value& blame_input_value,
33                           const StringType& input_value,
34                           Err* err) {
35   if (as_file) {
36     // It's an error to resolve an empty string or one that is a directory
37     // (indicated by a trailing slash) because this is the function that expects
38     // to return a file.
39     if (input_value.empty()) {
40       *err = Err(blame_input_value, "Empty file path.",
41                  "You can't use empty strings as file paths.");
42       return false;
43     } else if (input_value[input_value.size() - 1] == '/') {
44       std::string help = "You specified the path\n  ";
45       help.append(std::string(input_value));
46       help.append(
47           "\nand it ends in a slash, indicating you think it's a directory."
48           "\nBut here you're supposed to be listing a file.");
49       *err = Err(blame_input_value, "File path ends in a slash.", help);
50       return false;
51     }
52   } else if (input_value.empty()) {
53     *err = Err(blame_input_value, "Empty directory path.",
54                "You can't use empty strings as directories.");
55     return false;
56   }
57   return true;
58 }
59 
60 }  // namespace
61 
SourceDir(const std::string & s)62 SourceDir::SourceDir(const std::string& s) : value_(s) {
63   if (!EndsWithSlash(value_))
64     value_.push_back('/');
65   AssertValueSourceDirString(value_);
66 }
67 
SourceDir(std::string && s)68 SourceDir::SourceDir(std::string&& s) : value_(std::move(s)) {
69   if (!EndsWithSlash(value_))
70     value_.push_back('/');
71   AssertValueSourceDirString(value_);
72 }
73 
74 template <typename StringType>
ResolveRelativeAs(bool as_file,const Value & blame_input_value,const StringType & input_value,Err * err,const std::string_view & source_root) const75 std::string SourceDir::ResolveRelativeAs(
76     bool as_file,
77     const Value& blame_input_value,
78     const StringType& input_value,
79     Err* err,
80     const std::string_view& source_root) const {
81   if (!ValidateResolveInput<StringType>(as_file, blame_input_value, input_value,
82                                         err)) {
83     return std::string();
84   }
85   return ResolveRelative(input_value, value_, as_file, source_root);
86 }
87 
ResolveRelativeFile(const Value & p,Err * err,const std::string_view & source_root) const88 SourceFile SourceDir::ResolveRelativeFile(
89     const Value& p,
90     Err* err,
91     const std::string_view& source_root) const {
92   SourceFile ret;
93 
94   if (!p.VerifyTypeIs(Value::STRING, err))
95     return ret;
96 
97   const std::string& input_string = p.string_value();
98   if (!ValidateResolveInput<std::string>(true, p, input_string, err))
99     return ret;
100 
101   ret.SetValue(ResolveRelative(input_string, value_, true, source_root));
102   return ret;
103 }
104 
ResolveRelativeAs(bool as_file,const Value & v,Err * err,const std::string_view & source_root,const std::string * v_value) const105 std::string SourceDir::ResolveRelativeAs(bool as_file,
106                                          const Value& v,
107                                          Err* err,
108                                          const std::string_view& source_root,
109                                          const std::string* v_value) const {
110   if (!v.VerifyTypeIs(Value::STRING, err))
111     return std::string();
112 
113   if (!v_value) {
114     v_value = &v.string_value();
115   }
116   std::string result =
117       ResolveRelativeAs(as_file, v, *v_value, err, source_root);
118   if (!as_file)
119     AssertValueSourceDirString(result);
120   return result;
121 }
122 
ResolveRelativeDir(const Value & v,Err * err,const std::string_view & source_root) const123 SourceDir SourceDir::ResolveRelativeDir(
124     const Value& v,
125     Err* err,
126     const std::string_view& source_root) const {
127   if (!v.VerifyTypeIs(Value::STRING, err))
128     return SourceDir();
129 
130   return ResolveRelativeDir<std::string>(v, v.string_value(), err, source_root);
131 }
132 
Resolve(const base::FilePath & source_root) const133 base::FilePath SourceDir::Resolve(const base::FilePath& source_root) const {
134   return ResolvePath(value_, false, source_root);
135 }
136 
137 // Explicit template instantiation
138 template std::string SourceDir::ResolveRelativeAs(
139     bool as_file,
140     const Value& blame_input_value,
141     const std::string& input_value,
142     Err* err,
143     const std::string_view& source_root) const;
144 
145 template std::string SourceDir::ResolveRelativeAs(
146     bool as_file,
147     const Value& blame_input_value,
148     const std::string_view& input_value,
149     Err* err,
150     const std::string_view& source_root) const;
151