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#ifndef TOOLS_GN_SOURCE_FILE_H_
6#define TOOLS_GN_SOURCE_FILE_H_
7
8#include <algorithm>
9#include <string>
10
11#include "base/containers/hash_tables.h"
12#include "base/files/file_path.h"
13#include "base/logging.h"
14#include "base/strings/string_piece.h"
15
16class SourceDir;
17
18// Represents a file within the source tree. Always begins in a slash, never
19// ends in one.
20class SourceFile {
21 public:
22  enum SwapIn { SWAP_IN };
23
24  SourceFile();
25
26  // Takes a known absolute source file. Always begins in a slash.
27  explicit SourceFile(const base::StringPiece& p);
28
29  // Constructs from the given string by swapping in the contents of the given
30  // value. The value will be the empty string after this call.
31  SourceFile(SwapIn, std::string* value);
32
33  ~SourceFile();
34
35  bool is_null() const { return value_.empty(); }
36  const std::string& value() const { return value_; }
37
38  // Returns everything after the last slash.
39  std::string GetName() const;
40  SourceDir GetDir() const;
41
42  // Resolves this source file relative to some given source root. Returns
43  // an empty file path on error.
44  base::FilePath Resolve(const base::FilePath& source_root) const;
45
46  // Returns true if this file starts with a "//" which indicates a path
47  // from the source root.
48  bool is_source_absolute() const {
49    return value_.size() >= 2 && value_[0] == '/' && value_[1] == '/';
50  }
51
52  // Returns true if this file starts with a single slash which indicates a
53  // system-absolute path.
54  bool is_system_absolute() const {
55    return !is_source_absolute();
56  }
57
58  // Returns a source-absolute path starting with only one slash at the
59  // beginning (normally source-absolute paths start with two slashes to mark
60  // them as such). This is normally used when concatenating names together.
61  //
62  // This function asserts that the file is actually source-absolute. The
63  // return value points into our buffer.
64  base::StringPiece SourceAbsoluteWithOneSlash() const {
65    CHECK(is_source_absolute());
66    return base::StringPiece(&value_[1], value_.size() - 1);
67  }
68
69  bool operator==(const SourceFile& other) const {
70    return value_ == other.value_;
71  }
72  bool operator!=(const SourceFile& other) const {
73    return !operator==(other);
74  }
75  bool operator<(const SourceFile& other) const {
76    return value_ < other.value_;
77  }
78
79  void swap(SourceFile& other) {
80    value_.swap(other.value_);
81  }
82
83 private:
84  friend class SourceDir;
85
86  std::string value_;
87
88  // Copy & assign supported.
89};
90
91namespace BASE_HASH_NAMESPACE {
92
93#if defined(COMPILER_GCC)
94template<> struct hash<SourceFile> {
95  std::size_t operator()(const SourceFile& v) const {
96    hash<std::string> h;
97    return h(v.value());
98  }
99};
100#elif defined(COMPILER_MSVC)
101inline size_t hash_value(const SourceFile& v) {
102  return hash_value(v.value());
103}
104#endif  // COMPILER...
105
106}  // namespace BASE_HASH_NAMESPACE
107
108inline void swap(SourceFile& lhs, SourceFile& rhs) {
109  lhs.swap(rhs);
110}
111
112#endif  // TOOLS_GN_SOURCE_FILE_H_
113