• 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(std::string_view s)16 void AssertValueSourceDirString(std::string_view 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.
ValidateResolveInput(bool as_file,const Value & blame_input_value,std::string_view input_value,Err * err)30 bool ValidateResolveInput(bool as_file,
31                           const Value& blame_input_value,
32                           std::string_view input_value,
33                           Err* err) {
34   if (as_file) {
35     // It's an error to resolve an empty string or one that is a directory
36     // (indicated by a trailing slash) because this is the function that expects
37     // to return a file.
38     if (input_value.empty()) {
39       *err = Err(blame_input_value, "Empty file path.",
40                  "You can't use empty strings as file paths.");
41       return false;
42     } else if (input_value[input_value.size() - 1] == '/') {
43       std::string help = "You specified the path\n  ";
44       help.append(std::string(input_value));
45       help.append(
46           "\nand it ends in a slash, indicating you think it's a directory."
47           "\nBut here you're supposed to be listing a file.");
48       *err = Err(blame_input_value, "File path ends in a slash.", help);
49       return false;
50     }
51   } else if (input_value.empty()) {
52     *err = Err(blame_input_value, "Empty directory path.",
53                "You can't use empty strings as directories.");
54     return false;
55   }
56   return true;
57 }
58 
SourceDirStringAtom(std::string_view s)59 static StringAtom SourceDirStringAtom(std::string_view s) {
60   if (EndsWithSlash(s)) {  // Avoid allocation when possible.
61     AssertValueSourceDirString(s);
62     return StringAtom(s);
63   }
64 
65   std::string str;
66   str.reserve(s.size() + 1);
67   str += s;
68   str.push_back('/');
69   AssertValueSourceDirString(str);
70   return StringAtom(str);
71 }
72 
73 }  // namespace
74 
SourceDir(std::string_view s)75 SourceDir::SourceDir(std::string_view s) : value_(SourceDirStringAtom(s)) {}
76 
ResolveRelativeAs(bool as_file,const Value & blame_input_value,std::string_view input_value,Err * err,std::string_view source_root) const77 std::string SourceDir::ResolveRelativeAs(bool as_file,
78                                          const Value& blame_input_value,
79                                          std::string_view input_value,
80                                          Err* err,
81                                          std::string_view source_root) const {
82   if (!ValidateResolveInput(as_file, blame_input_value, input_value, err)) {
83     return std::string();
84   }
85   return ResolveRelative(input_value, value_.str(), as_file, source_root);
86 }
87 
ResolveRelativeFile(const Value & p,Err * err,std::string_view source_root) const88 SourceFile SourceDir::ResolveRelativeFile(const Value& p,
89                                           Err* err,
90                                           std::string_view source_root) const {
91   SourceFile ret;
92 
93   if (!p.VerifyTypeIs(Value::STRING, err))
94     return ret;
95 
96   const std::string& input_string = p.string_value();
97   if (!ValidateResolveInput(true, p, input_string, err))
98     return ret;
99 
100   ret.SetValue(ResolveRelative(input_string, value_.str(), true, source_root));
101   return ret;
102 }
103 
ResolveRelativeDir(const Value & blame_input_value,std::string_view input_value,Err * err,std::string_view source_root) const104 SourceDir SourceDir::ResolveRelativeDir(const Value& blame_input_value,
105                                         std::string_view input_value,
106                                         Err* err,
107                                         std::string_view source_root) const {
108   SourceDir ret;
109   ret.value_ = StringAtom(ResolveRelativeAs(false, blame_input_value,
110                                             input_value, err, source_root));
111   return ret;
112 }
113 
ResolveRelativeAs(bool as_file,const Value & v,Err * err,std::string_view source_root,const std::string * v_value) const114 std::string SourceDir::ResolveRelativeAs(bool as_file,
115                                          const Value& v,
116                                          Err* err,
117                                          std::string_view source_root,
118                                          const std::string* v_value) const {
119   if (!v.VerifyTypeIs(Value::STRING, err))
120     return std::string();
121 
122   if (!v_value) {
123     v_value = &v.string_value();
124   }
125   std::string result =
126       ResolveRelativeAs(as_file, v, *v_value, err, source_root);
127   if (!as_file)
128     AssertValueSourceDirString(result);
129   return result;
130 }
131 
ResolveRelativeDir(const Value & v,Err * err,std::string_view source_root) const132 SourceDir SourceDir::ResolveRelativeDir(const Value& v,
133                                         Err* err,
134                                         std::string_view source_root) const {
135   if (!v.VerifyTypeIs(Value::STRING, err))
136     return SourceDir();
137 
138   return ResolveRelativeDir(v, v.string_value(), err, source_root);
139 }
140 
Resolve(const base::FilePath & source_root) const141 base::FilePath SourceDir::Resolve(const base::FilePath& source_root) const {
142   return ResolvePath(value_.str(), false, source_root);
143 }
144