source_dir.cc revision 3551c9c881056c480085172ff9840cab31610854
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
11namespace {
12
13void AssertValueSourceDirString(const std::string& s) {
14  DCHECK(!s.empty());
15  DCHECK(s[0] == '/');
16  DCHECK(EndsWithSlash(s));
17}
18
19}  // namespace
20
21SourceDir::SourceDir() {
22}
23
24SourceDir::SourceDir(const base::StringPiece& p)
25    : value_(p.data(), p.size()) {
26  if (!EndsWithSlash(value_))
27    value_.push_back('/');
28  AssertValueSourceDirString(value_);
29}
30
31SourceDir::~SourceDir() {
32}
33
34SourceFile SourceDir::ResolveRelativeFile(
35    const base::StringPiece& p,
36    const base::StringPiece& source_root) const {
37  SourceFile ret;
38
39  // It's an error to resolve an empty string or one that is a directory
40  // (indicated by a trailing slash) because this is the function that expects
41  // to return a file.
42  if (p.empty() || (p.size() > 0 && p[p.size() - 1] == '/'))
43    return SourceFile();
44  if (p.size() >= 2 && p[0] == '/' && p[1] == '/') {
45    // Source-relative.
46    ret.value_.assign(p.data(), p.size());
47    NormalizePath(&ret.value_);
48    return ret;
49  } else if (IsPathAbsolute(p)) {
50    if (source_root.empty() ||
51        !MakeAbsolutePathRelativeIfPossible(source_root, p, &ret.value_))
52      ret.value_.assign(p.data(), p.size());
53    NormalizePath(&ret.value_);
54    return ret;
55  }
56
57  ret.value_.reserve(value_.size() + p.size());
58  ret.value_.assign(value_);
59  ret.value_.append(p.data(), p.size());
60
61  NormalizePath(&ret.value_);
62  return ret;
63}
64
65SourceDir SourceDir::ResolveRelativeDir(
66    const base::StringPiece& p,
67    const base::StringPiece& source_root) const {
68  SourceDir ret;
69
70  if (p.empty())
71    return ret;
72  if (p.size() >= 2 && p[0] == '/' && p[1] == '/') {
73    // Source-relative.
74    ret.value_.assign(p.data(), p.size());
75    if (!EndsWithSlash(ret.value_))
76      ret.value_.push_back('/');
77    NormalizePath(&ret.value_);
78    return ret;
79  } else if (IsPathAbsolute(p)) {
80    if (source_root.empty() ||
81        !MakeAbsolutePathRelativeIfPossible(source_root, p, &ret.value_))
82      ret.value_.assign(p.data(), p.size());
83    NormalizePath(&ret.value_);
84    if (!EndsWithSlash(ret.value_))
85      ret.value_.push_back('/');
86    return SourceDir(p);
87  }
88
89  ret.value_.reserve(value_.size() + p.size());
90  ret.value_.assign(value_);
91  ret.value_.append(p.data(), p.size());
92
93  NormalizePath(&ret.value_);
94  if (!EndsWithSlash(ret.value_))
95    ret.value_.push_back('/');
96  AssertValueSourceDirString(ret.value_);
97
98  return ret;
99}
100
101base::FilePath SourceDir::Resolve(const base::FilePath& source_root) const {
102  if (is_null())
103    return base::FilePath();
104
105  std::string converted;
106  if (is_system_absolute()) {
107    converted = value_;
108    ConvertPathToSystem(&converted);
109    return base::FilePath(UTF8ToFilePath(converted));
110  }
111
112  // String the double-leading slash for source-relative paths.
113  converted.assign(&value_[2], value_.size() - 2);
114  ConvertPathToSystem(&converted);
115  return source_root.Append(UTF8ToFilePath(converted));
116}
117
118void SourceDir::SwapInValue(std::string* v) {
119  value_.swap(*v);
120  AssertValueSourceDirString(value_);
121}
122