81340f94d2b4988af701bdfbae076310e4b571f8
[platform/framework/web/crosswalk.git] / src / tools / gn / source_dir.cc
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 "tools/gn/source_dir.h"
6
7 #include "base/logging.h"
8 #include "tools/gn/filesystem_utils.h"
9 #include "tools/gn/source_file.h"
10
11 namespace {
12
13 void AssertValueSourceDirString(const std::string& s) {
14   if (!s.empty()) {
15     DCHECK(s[0] == '/');
16     DCHECK(EndsWithSlash(s));
17   }
18 }
19
20 }  // namespace
21
22 SourceDir::SourceDir() {
23 }
24
25 SourceDir::SourceDir(const base::StringPiece& p)
26     : value_(p.data(), p.size()) {
27   if (!EndsWithSlash(value_))
28     value_.push_back('/');
29   AssertValueSourceDirString(value_);
30 }
31
32 SourceDir::SourceDir(SwapIn, std::string* s) {
33   value_.swap(*s);
34   if (!EndsWithSlash(value_))
35     value_.push_back('/');
36   AssertValueSourceDirString(value_);
37 }
38
39 SourceDir::~SourceDir() {
40 }
41
42 SourceFile SourceDir::ResolveRelativeFile(
43     const base::StringPiece& p,
44     const base::StringPiece& source_root) const {
45   SourceFile ret;
46
47   // It's an error to resolve an empty string or one that is a directory
48   // (indicated by a trailing slash) because this is the function that expects
49   // to return a file.
50   if (p.empty() || (p.size() > 0 && p[p.size() - 1] == '/'))
51     return SourceFile();
52   if (p.size() >= 2 && p[0] == '/' && p[1] == '/') {
53     // Source-relative.
54     ret.value_.assign(p.data(), p.size());
55     NormalizePath(&ret.value_);
56     return ret;
57   } else if (IsPathAbsolute(p)) {
58     if (source_root.empty() ||
59         !MakeAbsolutePathRelativeIfPossible(source_root, p, &ret.value_)) {
60 #if defined(OS_WIN)
61       // On Windows we'll accept "C:\foo" as an absolute path, which we want
62       // to convert to "/C:..." here.
63       if (p[0] != '/')
64         ret.value_ = "/";
65 #endif
66       ret.value_.append(p.data(), p.size());
67     }
68     NormalizePath(&ret.value_);
69     return ret;
70   }
71
72   ret.value_.reserve(value_.size() + p.size());
73   ret.value_.assign(value_);
74   ret.value_.append(p.data(), p.size());
75
76   NormalizePath(&ret.value_);
77   return ret;
78 }
79
80 SourceDir SourceDir::ResolveRelativeDir(
81     const base::StringPiece& p,
82     const base::StringPiece& source_root) const {
83   SourceDir ret;
84
85   if (p.empty())
86     return ret;
87   if (p.size() >= 2 && p[0] == '/' && p[1] == '/') {
88     // Source-relative.
89     ret.value_.assign(p.data(), p.size());
90     if (!EndsWithSlash(ret.value_))
91       ret.value_.push_back('/');
92     NormalizePath(&ret.value_);
93     return ret;
94   } else if (IsPathAbsolute(p)) {
95     if (source_root.empty() ||
96         !MakeAbsolutePathRelativeIfPossible(source_root, p, &ret.value_)) {
97 #if defined(OS_WIN)
98       if (p[0] != '/')  // See the file case for why we do this check.
99         ret.value_ = "/";
100 #endif
101       ret.value_.append(p.data(), p.size());
102     }
103     NormalizePath(&ret.value_);
104     if (!EndsWithSlash(ret.value_))
105       ret.value_.push_back('/');
106     return ret;
107   }
108
109   ret.value_.reserve(value_.size() + p.size());
110   ret.value_.assign(value_);
111   ret.value_.append(p.data(), p.size());
112
113   NormalizePath(&ret.value_);
114   if (!EndsWithSlash(ret.value_))
115     ret.value_.push_back('/');
116   AssertValueSourceDirString(ret.value_);
117
118   return ret;
119 }
120
121 base::FilePath SourceDir::Resolve(const base::FilePath& source_root) const {
122   if (is_null())
123     return base::FilePath();
124
125   std::string converted;
126   if (is_system_absolute()) {
127     if (value_.size() > 2 && value_[2] == ':') {
128       // Windows path, strip the leading slash.
129       converted.assign(&value_[1], value_.size() - 1);
130     } else {
131       converted.assign(value_);
132     }
133     ConvertPathToSystem(&converted);
134     return base::FilePath(UTF8ToFilePath(converted));
135   }
136
137   // String the double-leading slash for source-relative paths.
138   converted.assign(&value_[2], value_.size() - 2);
139   ConvertPathToSystem(&converted);
140   return source_root.Append(UTF8ToFilePath(converted));
141 }
142
143 void SourceDir::SwapValue(std::string* v) {
144   value_.swap(*v);
145   AssertValueSourceDirString(value_);
146 }