aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/cpp/rc_file.h
blob: 0d462dcc4bca7a0969d8732b79df035aa91d1b5b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// Copyright 2018 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef BAZEL_SRC_MAIN_CPP_RC_FILE_H_
#define BAZEL_SRC_MAIN_CPP_RC_FILE_H_

#include <deque>
#include <memory>
#include <unordered_map>
#include <string>
#include <vector>

#include "src/main/cpp/workspace_layout.h"

namespace blaze {

// Single option in an rc file.
struct RcOption {
  // Keep a pointer to the path string to avoid copying it over and over.
  std::string* source_path;
  std::string option;
};

// Reads and parses a single rc file with all its imports.
class RcFile {
 public:
  // Constructs a parsed rc file object, or returns a nullptr and sets the
  // error and error text on failure.
  enum class ParseError { NONE, UNREADABLE_FILE, INVALID_FORMAT, IMPORT_LOOP };
  static std::unique_ptr<RcFile> Parse(
      std::string filename, const WorkspaceLayout* workspace_layout,
      std::string workspace, ParseError* error, std::string* error_text);

  // Returns all relevant rc sources for this file (including itself).
  const std::deque<std::string>& sources() const { return rcfile_paths_; }

  // Command -> all options for that command (in order of appearance).
  using OptionMap = std::unordered_map<std::string, std::vector<RcOption>>;
  const OptionMap& options() const { return options_; }

 private:
  RcFile(std::string filename, const WorkspaceLayout* workspace_layout,
         std::string workspace);
  // Don't allow copying or moving because it can be tricky with the RcOption
  // string pointers.
  RcFile(const RcFile&) = delete;
  RcFile& operator=(const RcFile&) = delete;

  // Recursive call to parse a file and its imports.
  ParseError ParseFile(const std::string& filename,
                       std::deque<std::string>* import_stack,
                       std::string* error_text);

  const std::string filename_;

  // Workspace definition.
  const WorkspaceLayout* const workspace_layout_;
  const std::string workspace_;

  // Full closure of rcfile paths imported from this file (including itself).
  // The RcOption structs point to the strings in here so they need to be stored
  // in a container that offers stable pointers, like a deque (and not vector).
  std::deque<std::string> rcfile_paths_;
  // All options parsed from the file.
  OptionMap options_;
};

}  // namespace blaze

#endif  // BAZEL_SRC_MAIN_CPP_RC_FILE_H_