licornea_tools
args.cc
Go to the documentation of this file.
1 #include "args.h"
2 #include <iostream>
3 #include <cstdlib>
4 #include "misc.h"
5 #include "filesystem.h"
6 #include "string.h"
7 
8 namespace tlz {
9 
10 namespace {
11 
12 std::string out_filename_(const std::string& filename) {
13  if(filename == "") return "";
14  make_parent_directories(filename);
15  if(file_exists(filename)) {
16  if(batch_mode()) {
17  std::cout << "overwriting existing output file " << filename << std::endl;
18  } else {
19  std::cout << "output file " << filename << " exists. Proceed? [y/n] ";
20  char answer;
21  std::cin >> answer;
22  if(answer != 'y' && answer != 'Y') throw std::runtime_error("not overwriting output file, exiting");
23  }
24  }
25  return filename;
26 }
27 
28 std::string out_dirname_(const std::string& dirname) {
29  if(dirname == "") return "";
30  if(! file_exists(dirname)) {
31  make_parent_directories(dirname);
32  make_directory(dirname);
33  } else {
34  if(! is_directory(dirname)) throw std::runtime_error("file exists at " + dirname);
35  }
36  return dirname;
37 }
38 
39 }
40 
41 std::unique_ptr<args_list> args_list::instance = std::unique_ptr<args_list>();
42 
44  if(args_list::instance) return *args_list::instance;
45  else throw std::logic_error("args_list not initialized (get_args was not called)");
46 }
47 
48 
49 void get_args(int argc, const char* argv[], const std::string& usage) {
50  if(argc >= 2 && std::string(argv[1]) == "--help") {
51  std::cout << "usage: " << argv[0] << " " << usage << std::endl;
52  std::exit(EXIT_SUCCESS);
53  }
54  args_list::instance = std::make_unique<args_list>(argc, argv, usage);
55 }
56 
57 
58 bool batch_mode() {
59  const char* batch_mode_env = std::getenv("LICORNEA_BATCH_MODE");
60  if(batch_mode_env == nullptr) return false;
61  else return (std::string(batch_mode_env) == "1");
62 }
63 
64 args_list::args_list(int argc, const char* argv[], const std::string& usage) :
65  executable_name_(argv[0]),
66  usage_(usage),
67  arg_index_(0)
68 {
69  for(int i = 1; i < argc; ++i) args_.push_back(argv[i]);
70 }
71 
72 void args_list::usage_fail(const std::string& error) const {
73  std::cerr << "usage: " << executable_name_ << ' ' << usage_ << std::endl;
74  if(! error.empty()) std::cerr << " " << error << std::endl;
75  std::exit(EXIT_FAILURE);
76 }
77 
78 const char* args_list::next_arg() {
79  if(arg_index_ >= args_.size())
80  usage_fail("more than " + std::to_string(args_.size()) + " arguments needed");
81  return args_.at(arg_index_++);
82 }
83 
84 bool args_list::next_arg_is(const std::string& val) const {
85  if(arg_index_ >= args_.size())
86  usage_fail("more than " + std::to_string(args_.size()) + " arguments needed");
87  return (val == args_.at(arg_index_));
88 }
89 
91  return (arg_index_ < args_.size());
92 }
93 
94 std::string string_arg() {
95  return std::string(args().next_arg());
96 }
97 
98 std::string in_filename_arg() {
99  const std::string& filename = string_arg();
100  if(!file_exists(filename)) args().usage_fail("file " + filename + " does not exist");
101  return filename;
102 }
103 
104 std::string out_filename_arg() {
105  const std::string& filename = string_arg();
106  if(filename == "-") throw std::runtime_error("expected filename argument, not -");
107  return out_filename_(filename);
108 }
109 
110 std::string out_filename_opt_arg(const std::string& def) {
111  if(! args().has_next_arg()) {
112  return out_filename_(def);
113  } else if(args().next_arg_is("-")) {
114  args().next_arg();
115  return out_filename_(def);;
116  } else {
117  return out_filename_arg();
118  }
119 }
120 
121 std::string out_dirname_arg() {
122  const std::string& dirname = string_arg();
123  if(dirname == "-") throw std::runtime_error("expected dirname argument, not -");
124  return out_dirname_(dirname);
125 }
126 
127 std::string out_dirname_opt_arg(const std::string& def) {
128  if(! args().has_next_arg()) {
129  return out_dirname_(def);
130  } else if(args().next_arg_is("-")) {
131  args().next_arg();
132  return out_dirname_(def);
133  } else {
134  return out_dirname_arg();
135  }
136 }
137 
138 long int_arg() {
139  const char* str = args().next_arg();
140  char* str_end;
141  long i = std::strtol(str, &str_end, 10);
142  if(str_end == str) args().usage_fail("`" + std::string(str) + "` is not an integer");
143  return i;
144 }
145 
146 double real_arg() {
147  const char* str = args().next_arg();
148  char* str_end;
149  double f = std::strtod(str, &str_end);
150  if(str_end == str) args().usage_fail("`" + std::string(str) + "` is not a real");
151  return f;
152 }
153 
154 std::string enum_arg(const std::vector<std::string>& options) {
155  const char* str = args().next_arg();
156  for(const std::string& option : options)
157  if(str == option) return option;
158  args().usage_fail("`" + std::string(str) + "` invalid value");
159 }
160 
161 bool bool_arg(const std::string& expected) {
162  const char* str = args().next_arg();
163  return (str == expected);
164 }
165 
167  const std::string& str = string_arg();
168  view_index idx;
169  auto j_idx = explode_from_string<int>(',', str);
170  idx.x = j_idx[0];
171  if(j_idx.size() == 2) idx.y = j_idx[1];
172  else idx.y = -1;
173  return idx;
174 }
175 
176 }
args_list(int argc, const char *argv[], const std::string &usage)
Definition: args.cc:64
bool file_exists(const std::string &filename)
bool bool_arg(const std::string &expected)
Definition: args.cc:161
bool has_next_arg() const
Definition: args.cc:90
void usage_fail(const std::string &error="") const
Definition: args.cc:72
const char * next_arg()
Definition: args.cc:78
std::string in_filename_arg()
Definition: args.cc:98
std::string enum_arg(const std::vector< std::string > &options)
Definition: args.cc:154
bool is_directory(const std::string &filename)
static std::unique_ptr< args_list > instance
Definition: args.h:19
std::string out_filename_opt_arg(const std::string &def)
Definition: args.cc:110
std::string out_dirname_arg()
Definition: args.cc:121
long int_arg()
Definition: args.cc:138
bool batch_mode()
Definition: args.cc:58
std::string string_arg()
Definition: args.cc:94
double real_arg()
Definition: args.cc:146
std::string out_dirname_opt_arg(const std::string &def)
Definition: args.cc:127
std::string to_string(const T &)
std::string out_filename_arg()
Definition: args.cc:104
void make_directory(const std::string &dirname)
bool next_arg_is(const std::string &val) const
Definition: args.cc:84
args_list & args()
Definition: args.cc:43
void make_parent_directories(const std::string &filename)
view_index view_index_arg()
Definition: args.cc:166
void get_args(int argc, const char *argv[], const std::string &usage)
Definition: args.cc:49