SIRIUS 7.5.0
Electronic structure library and applications
cmd_args.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2020 Anton Kozhevnikov, Thomas Schulthess
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
5// the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
8// following disclaimer.
9// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
10// and the following disclaimer in the documentation and/or other materials provided with the distribution.
11//
12// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
13// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
15// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
16// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
18// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
20/** \file cmd_args.hpp
21 *
22 * \brief Contains definition and implementation of cmd_args class.
23 */
24
25#ifndef __CMD_ARGS_HPP__
26#define __CMD_ARGS_HPP__
27
28#include <vector>
29#include <string>
30#include <map>
31#include <sstream>
32#include <algorithm>
33#include <iostream>
34
35namespace sirius {
36
37/// Simple command line arguments handler.
39{
40 private:
41 /// Helper string for each key.
42 std::vector<std::pair<std::string, std::string>> key_desc_;
43
44 /// Mapping between a key and its kind (with or without value).
45 std::map<std::string, int> known_keys_;
46
47 /// Key to value mapping.
48 std::map<std::string, std::string> keys_;
49
50 template <typename T>
51 std::vector<T> get_vector(std::string const key__) const
52 {
53 auto s = keys_.at(key__);
54 std::replace(s.begin(), s.end(), ':', ' ');
55 std::istringstream iss(s);
56 std::vector<T> v;
57 while (!iss.eof()) {
58 T k;
59 iss >> k;
60 v.push_back(k);
61 }
62 return v;
63 }
64
65 template <typename T, std::size_t N>
66 std::array<T, N> get_array(std::string const key__) const
67 {
68 auto v = this->get_vector<T>(key__);
69 if (v.size() != N) {
70 std::stringstream s;
71 s << "[cmd_args::get_array] wrong size of array for the command-line argument " << key__ << std::endl
72 << "[cmd_args::get_array] expected size : " << N << ", provided size : " << v.size();
73 throw std::runtime_error(s.str());
74 } else {
75 std::array<T, N> out;
76 out.fill(T{}); // prevent compiler warning about uninitialized array
77 std::copy(v.begin(), v.end(), out.begin());
78 return out;
79 }
80 }
81
82 void check_for_key(std::string const key__) const;
83
84 public:
85 /// Constructor.
86 cmd_args();
87
88 /// Constructor with the list of keys.
89 /** The following example shows how to initialize arguments:
90 \code{.cpp}
91 cmd_args args(argn, argv, {
92 {"device=", "(string) CPU or GPU"},
93 {"pw_cutoff=", "(double) plane-wave cutoff for density and potential"},
94 {"N=", "(int) cell multiplicity"}
95 });
96 \endcode
97 */
98 cmd_args(int argn__, char** argv__, std::initializer_list<std::pair<std::string, std::string>> keys__);
99
100 void register_key(std::string const key__, std::string const description__);
101
102 void parse_args(int argn__, char** argv__);
103
104 void print_help();
105
106 inline bool exist(const std::string key__) const
107 {
108 return keys_.count(key__);
109 }
110
111 /// Get a value or terminate if key is not found.
112 template <typename T>
113 inline T value(std::string const key__) const
114 {
115 check_for_key(key__);
116 T v;
117 std::istringstream(keys_.at(key__)) >> v;
118 return v;
119 }
120
121 ///// Get a vector of values or terminate if key is not found.
122 //template <typename T>
123 //inline std::vector<T> value(std::string const key__) const
124 //{
125 // check_for_key(key__);
126 // return get_vector<T>(key__);
127 //}
128
129 //template <typename T, std::size_t N>
130 //inline std::array<T, N> value(std::string const key__) const
131 //{
132 // check_for_key(key__);
133 // return get_array<T, N>(key__);
134 //}
135
136
137 /// Get a value if key exists or return a default value.
138 template <typename T>
139 inline T value(std::string const key__, T default_val__) const
140 {
141 if (!exist(key__)) {
142 return default_val__;
143 }
144 T v;
145 std::istringstream(keys_.at(key__)) >> v;
146 return v;
147 }
148
149 template <typename T>
150 inline std::vector<T> value(std::string const key__, std::vector<T> default_val__) const
151 {
152 if (!exist(key__)) {
153 return default_val__;
154 }
155 return get_vector<T>(key__);
156 }
157
158 template <typename T, std::size_t N>
159 inline std::array<T, N> value(std::string const key__, std::array<T, N> default_val__) const
160 {
161 if (!exist(key__)) {
162 return default_val__;
163 }
164 return get_array<T, N>(key__);
165 }
166
167 std::string operator[](const std::string key__) const
168 {
169 return keys_.at(key__);
170 }
171
172 std::map<std::string, std::string> keys() const
173 {
174 return keys_;
175 }
176};
177
178template <>
179inline std::string cmd_args::value<std::string>(const std::string key__) const
180{
181 return keys_.at(key__);
182}
183
184template <>
185inline std::string cmd_args::value<std::string>(const std::string key__, const std::string default_val__) const
186{
187 if (!exist(key__)) {
188 return default_val__;
189 }
190 return keys_.at(key__);
191}
192
193template <>
194inline std::vector<double> cmd_args::value<std::vector<double>>(const std::string key__) const
195{
196 check_for_key(key__);
197 return get_vector<double>(key__);
198}
199
200template <>
201inline std::vector<int> cmd_args::value<std::vector<int>>(const std::string key__) const
202{
203 check_for_key(key__);
204 return get_vector<int>(key__);
205}
206
207} // namespace sirius
208
209#endif // __CMD_ARGS_HPP__
Simple command line arguments handler.
Definition: cmd_args.hpp:39
std::vector< std::pair< std::string, std::string > > key_desc_
Helper string for each key.
Definition: cmd_args.hpp:42
cmd_args()
Constructor.
Definition: cmd_args.cpp:39
T value(std::string const key__, T default_val__) const
Get a value if key exists or return a default value.
Definition: cmd_args.hpp:139
T value(std::string const key__) const
Get a value or terminate if key is not found.
Definition: cmd_args.hpp:113
std::map< std::string, int > known_keys_
Mapping between a key and its kind (with or without value).
Definition: cmd_args.hpp:45
std::map< std::string, std::string > keys_
Key to value mapping.
Definition: cmd_args.hpp:48
void copy(T *target__, T const *source__, size_t n__)
Copy memory inside a device.
Definition: acc.hpp:320
Namespace of the SIRIUS library.
Definition: sirius.f90:5