The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
options.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2012 - 2016 by Mark de Wever <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "wesmage/options.hpp"
16 
17 #include "wesmage/exit.hpp"
18 #include "wesmage/filter.hpp"
19 
20 #include <cassert>
21 #include <cstdlib>
22 #include <ctime>
23 #include <iostream>
24 
26  : input_filename()
27  , output_filename()
28  , filters()
29  , time(false)
30  , count(1)
31 {
32 }
33 
34 /*
35  * This function prints the option and its description in a nice fashion.
36  *
37  * * The description is indented at column tab_offset.
38  * * If the option text is short enough the description starts after it,
39  * properly indented. Else starts at the next line, again properly
40  * indented.
41  * * If the text of the description doesn't fit at a single line it split at
42  * space and continues on the next line, obviously indented again.
43  */
44 static void
46  std::ostream& stream
47  , const std::string& option
48  , std::string description)
49 {
50  const unsigned line_length = 80;
51  const unsigned tab_offset = 25;
52  const unsigned description_length = line_length - tab_offset;
53  const std::string tab_filler(tab_offset - 1, ' ');
54 
55  assert(!option.empty());
56  assert(!description.empty());
57 
58  stream << option;
59  if(option.length() < tab_offset - 1) {
60  stream << std::string(tab_offset - 1 - option.length(), ' ');
61  } else {
62  stream << '\n' << tab_filler;
63  }
64 
65  while(!description.empty()) {
66  size_t eol = description.find('\n');
67  if(eol <= description_length) {
68  stream << description.substr(0, eol);
69  description.erase(0, eol + 1);
70  } else if(description.size() <= description_length) {
71  stream << description;
72  description.clear();
73  } else {
74  int offset = description_length + 1;
75  while(description[offset] != ' ' && offset >= 0) {
76  --offset;
77  }
78  assert(offset != 0);
79  assert(description[offset] == ' ');
80 
81  stream << description.substr(0, offset);
82  description.erase(0, offset + 1);
83  }
84  stream << '\n';
85  if(!description.empty()) {
86  stream << tab_filler;
87  }
88  }
89 }
90 
91 static std::ostream&
93  std::ostream& stream
94  , const tfilter_description& fd)
95 {
96  print_option(stream, fd.name, fd.description);
99  stream
100  , " * " + p.name + " (" + p.type + ")"
101  , p.descripton);
102  }
103 
104  return stream;
105 }
106 
107 static void
108 print_help(const int exit_status)
109 {
110  std::cout <<
111 "Usage wesmage [OPTION...] [FILE]\n"
112 "Helper program to test image manipulation algorithms.\n"
113 "\n"
114 "The FILE is the name of the input file to be converted.\n"
115 "OPTIONS:\n"
116 "-o, --output FILE The name of the output file to be written.\n"
117 "-n, --dry-run No output is written.\n"
118 "-t, --time Show the time it took to apply the filters.\n"
119 " The resolution of the time depends on the platform.\n"
120 "-c, --count COUNT The number of times the filter needs to be applied.\n"
121 " This feature is mainly for timing an algorithm and\n"
122 " is applied on a new image every iteration.\n"
123 "-f, --filter FILTER Filters to be applied to the image. See FILTERS.\n"
124 "-h, --help Show this help and terminate the program.\n"
125 "\n"
126 "FILTERS:\n"
127 "A filter applies a modification to an image. The program can handle\n"
128 "multiple filters. They are applied from the command line. The are applied\n"
129 "in the left to right order they appear on the command line.\n"
130 "A filter has the following syntax ID:PARAMETERS where:\n"
131 "ID The id of the filter.\n"
132 "PARAMETERS Zero or more parameters. Multiple parameters are\n"
133 " separated by a comma. The number parameters required\n"
134 " depend on the filter.\n"
135 "\n"
136 "The following filters are currently implemented:\n"
137 ;
138  for(const tfilter_description& filter : filter_list()) {
139  std::cout << filter;
140  }
141 
142  throw texit(exit_status);
143 }
144 
145 #define VALIDATE_NOT_PAST_END \
146  do { \
147  if(i >= argc) { \
148  std::cerr << "Error: Required argument for the option »" \
149  << option \
150  << "« is not supplied.\n"; \
151  \
152  throw texit(EXIT_FAILURE); \
153  } \
154  } while(0)
155 
156 const toptions&
157 toptions::parse(int argc, char* argv[])
158 {
159  toptions& result = singleton(false);
160 
161  bool help = false;
162  bool dry_run = false;
163 
164  /* argv[0] is the name of the program, not a command-line argument. */
165  for(int i = 1; i < argc; ++i) {
166  const std::string option(argv[i]);
167 
168  if(option == "-h" || option == "--help") {
169  help = true;
170  } else if(option == "-n" || option == "--dry-run") {
171  dry_run = true;
172  } else if(option == "-t" || option == "--time") {
173  result.time = true;
174  } else if(option == "-c" || option == "--count") {
175  ++i;
177 
178  char* end;
179  result.count = strtol(argv[i], &end, 10);
180  if(*end || result.count <= 0) {
181  std::cerr << "Error: Parameter of count »"
182  << argv[i]
183  << "« should be a positive number.\n";
184  print_help(EXIT_FAILURE);
185  }
186  } else if(option.substr(0, 2) == "-c") {
187  char* end;
188  result.count = strtol(option.substr(2).c_str(), &end, 10);
189  if(*end || result.count <= 0) {
190  std::cerr << "Error: Parameter of count »"
191  << option.substr(2).c_str()
192  << "« should be a positive number.\n";
193  print_help(EXIT_FAILURE);
194  }
195  } else if(option == "-o" || option == "--output") {
196  ++i;
198  result.output_filename = argv[i];
199  } else if(option.substr(0, 2) == "-o") {
200  result.output_filename = option.substr(2);
201  } else if(option == "-f" || option == "--filter") {
202  ++i;
204  result.filters.push_back(argv[i]);
205  } else if(option.substr(0, 2) == "-f") {
206  result.filters.push_back(option.substr(2));
207  } else {
208  if(!result.input_filename.empty()) {
209  std::cerr << "Error: Command line argument »"
210  << option
211  << "« is not recognised.\n";
212 
213  print_help(EXIT_FAILURE);
214  }
215  result.input_filename = option;
216  }
217  }
218 
219  if(help) {
220  print_help(EXIT_SUCCESS);
221  }
222 
223  if(dry_run && !result.output_filename.empty()) {
224  std::cerr << "Error: Dry run with an output file is not allowed.\n";
225  print_help(EXIT_FAILURE);
226  }
227 
228  if(result.input_filename.empty()) {
229  std::cerr << "Error: Input filename omitted.\n";
230  print_help(EXIT_FAILURE);
231  }
232 
233  if(result.output_filename.empty() && !dry_run) {
234  std::cerr << "Error: Output filename omitted.\n";
235  print_help(EXIT_FAILURE);
236  }
237 
238  if(result.time && (std::clock() == -1)) {
239  std::cerr
240  << "Error: No timing available on your platform, "
241  << "option disabled.\n";
242 
243  result.time = false;
244  }
245 
246  /*
247  * No filter implies a copy, or conversion to png, which is a valid
248  * way to use the program, so do not complain.
249  */
250 
251  return result;
252 }
253 
254 const toptions&
256 {
257  return singleton(true);
258 }
259 
260 toptions&
261 toptions::singleton(const bool is_initialized)
262 {
263  static bool initialized = false;
264  assert(is_initialized == initialized);
265  initialized = true;
266 
267  static toptions result;
268  return result;
269 }
A singleton class containing the parsed command line parameters.
Definition: options.hpp:29
#define VALIDATE_NOT_PAST_END
Definition: options.cpp:145
static std::ostream & operator<<(std::ostream &stream, const tfilter_description &fd)
Definition: options.cpp:92
static std::map< std::string, tfilter > filters
The list of the available filters.
Definition: filter.cpp:77
bool time
Display the time that applying the filters took.
Definition: options.hpp:72
std::string name
Name of the filter.
Definition: filter.hpp:62
std::string output_filename
The filename of the output file.
Definition: options.hpp:66
GLuint GLenum option
Definition: glew.h:2815
static toptions & singleton(const bool is_initialized)
Helper which contains the single instance of this class.
Definition: options.cpp:261
GLintptr offset
Definition: glew.h:1650
GLuint GLuint stream
Definition: glew.h:5239
GLuint GLuint end
Definition: glew.h:1221
GLuint64EXT * result
Definition: glew.h:10727
Helper structure to describe what a filter does.
Definition: filter.hpp:36
static void print_option(std::ostream &stream, const std::string &option, std::string description)
Definition: options.cpp:45
std::string input_filename
The filename of the input file.
Definition: options.hpp:63
Describes a filter parameter.
Definition: filter.hpp:72
GLfloat GLfloat p
Definition: glew.h:12766
GLuint GLuint GLsizei count
Definition: glew.h:1221
const std::string eol
end of line + possible various character before.
std::string type
The C type of the parameter.
Definition: filter.hpp:78
std::vector< tparameter > parameters
The list of filter parameters.
Definition: filter.hpp:85
This exception when throw should terminate the application.
Definition: sdl2.cpp:35
toptions()
Definition: options.cpp:25
size_t i
Definition: function.cpp:1057
static Uint8 initialized
Exit exception.
static void print_help(const int exit_status)
Definition: options.cpp:108
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glew.h:3448
std::vector< tfilter_description > filter_list()
Returns the list of available filters.
Definition: filter.cpp:239
Command line parameters for wesmage.
Filters for wesmage.
Definition: help.cpp:57
std::string descripton
Describes what the parameter does.
Definition: filter.hpp:81
static const toptions & parse(int argc, char *argv[])
Parses the command line.
Definition: options.cpp:157
int count
The number of times the filter has to be applied.
Definition: options.hpp:79
static const toptions & options()
Returns the cached parsed command line parameters.
Definition: options.cpp:255
std::string name
The name of the parameter.
Definition: filter.hpp:75
GLsizei const GLcharARB ** string
Definition: glew.h:4503
std::string description
Description of the filter.
Definition: filter.hpp:69
std::vector< std::string > filters
The filters to apply to the input file.
Definition: options.hpp:69