summaryrefslogtreecommitdiff
path: root/src/Args.hpp
blob: 16bc7fe451294d41935965282facc322cc4f6b44 (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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright (C) 2020-2022 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the Free Software Foundation, Inc., 51
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

#pragma once

#include "NonCopyable.hpp"

#include <deque>
#include <optional>
#include <string>
#include <string_view>
#include <vector>

class Args
{
public:
  enum class AtFileFormat {
    gcc,  // '\'' and '"' quote, '\\' escapes any character
    msvc, // '"' quotes, '\\' escapes only '"' and '\\'
  };

  Args() = default;
  Args(const Args& other) = default;
  Args(Args&& other) noexcept;

  static Args from_argv(int argc, const char* const* argv);
  static Args from_string(std::string_view command);

  static std::optional<Args>
  from_atfile(const std::string& filename,
              AtFileFormat format = AtFileFormat::gcc);

  Args& operator=(const Args& other) = default;
  Args& operator=(Args&& other) noexcept;

  bool operator==(const Args& other) const;
  bool operator!=(const Args& other) const;

  bool empty() const;
  size_t size() const;
  const std::string& operator[](size_t i) const;
  std::string& operator[](size_t i);

  // Return the argument list as a vector of raw string pointers. Callers can
  // use `const_cast<char* const*>(args.to_argv().data())` to get an array
  // suitable to pass to e.g. execv(2).
  std::vector<const char*> to_argv() const;

  // Return a space-delimited argument list in string form. No quoting of spaces
  // in arguments is performed.
  std::string to_string() const;

  // Remove last argument equal to `arg`, if any.
  void erase_last(std::string_view arg);

  // Remove all arguments with prefix `prefix`.
  void erase_with_prefix(std::string_view prefix);

  // Insert arguments in `args` at position `index`.
  void insert(size_t index, const Args& args);

  // Remove the last `count` arguments.
  void pop_back(size_t count = 1);

  // Remove the first `count` arguments.
  void pop_front(size_t count = 1);

  // Add `arg` to the end.
  void push_back(const std::string& arg);

  // Add `args` to the end.
  void push_back(const Args& args);

  // Add `arg` to the front.
  void push_front(const std::string& arg);

  // Replace the argument at `index` with all arguments in `args`.
  void replace(size_t index, const Args& args);

private:
  std::deque<std::string> m_args;
};

inline bool
Args::operator==(const Args& other) const
{
  return m_args == other.m_args;
}

inline bool
Args::operator!=(const Args& other) const
{
  return m_args != other.m_args;
}

inline bool
Args::empty() const
{
  return m_args.empty();
}

inline size_t
Args::size() const
{
  return m_args.size();
}

inline const std::string&
Args::operator[](size_t i) const
{
  return m_args[i];
}

inline std::string&
Args::operator[](size_t i)
{
  return m_args[i];
}