2 * Copyright (c) 2014, Andrzej Rybczak <electricityispower@gmail.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the copyright holder nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
26 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #ifndef NCMPCPP_UTILITY_OPTION_PARSER_H
34 #define NCMPCPP_UTILITY_OPTION_PARSER_H
36 #include <boost/lexical_cast.hpp>
39 #include <unordered_map>
41 #include "utility/functional.h"
45 typedef std::function
<void(std::string
&&)> parser_t
;
46 typedef std::function
<void()> default_t
;
48 template <typename DestT
, typename SourceT
>
49 struct assign_value_once
51 typedef DestT dest_type
;
52 typedef typename
std::decay
<SourceT
>::type source_type
;
54 template <typename ArgT
>
55 assign_value_once(DestT
&dest
, ArgT
&&value
)
56 : m_dest(dest
), m_source(std::make_shared
<source_type
>(std::forward
<ArgT
>(value
))) { }
60 assert(m_source
.get() != nullptr);
61 m_dest
= std::move(*m_source
);
67 std::shared_ptr
<source_type
> m_source
;
70 template <typename IntermediateT
, typename DestT
, typename TransformT
>
71 struct parse_and_transform
73 template <typename ArgT
>
74 parse_and_transform(DestT
&dest
, ArgT
&&map
)
75 : m_dest(dest
), m_map(std::forward
<ArgT
>(map
)) { }
77 void operator()(std::string
&&v
)
80 m_dest
= m_map(boost::lexical_cast
<IntermediateT
>(v
));
81 } catch (boost::bad_lexical_cast
&) {
82 throw std::runtime_error("invalid value: " + v
);
95 template <typename ParserT
, typename DefaultT
>
96 worker(ParserT
&&p
, DefaultT
&&d
)
97 : m_defined(false), m_parser(std::forward
<ParserT
>(p
))
98 , m_default(std::forward
<DefaultT
>(d
)) { }
100 template <typename ValueT
>
101 void parse(ValueT
&&value
)
104 throw std::runtime_error("option already defined");
105 m_parser(std::forward
<ValueT
>(value
));
109 bool defined() const { return m_defined
; }
110 void run_default() const { m_default(); }
118 template <typename ParserT
, typename DefaultT
>
119 void add(const std::string
&option
, ParserT
&&p
, DefaultT
&&d
)
121 assert(m_parsers
.count(option
) == 0);
122 m_parsers
[option
] = worker(std::forward
<ParserT
>(p
), std::forward
<DefaultT
>(d
));
125 template <typename WorkerT
>
126 void add(const std::string
&option
, WorkerT
&&w
)
128 assert(m_parsers
.count(option
) == 0);
129 m_parsers
[option
] = std::forward
<WorkerT
>(w
);
132 bool run(std::istream
&is
);
135 std::unordered_map
<std::string
, worker
> m_parsers
;
138 template <typename IntermediateT
, typename ArgT
, typename TransformT
>
139 option_parser::parser_t
assign(ArgT
&arg
, TransformT
&&map
= id_())
141 return option_parser::parse_and_transform
<IntermediateT
, ArgT
, TransformT
>(
142 arg
, std::forward
<TransformT
>(map
)
146 template <typename ArgT
, typename ValueT
>
147 option_parser::default_t
defaults_to(ArgT
&arg
, ValueT
&&value
)
149 return option_parser::assign_value_once
<ArgT
, ValueT
>(
150 arg
, std::forward
<ValueT
>(value
)
154 template <typename IntermediateT
, typename ArgT
, typename ValueT
, typename TransformT
>
155 option_parser::worker
assign_default(ArgT
&arg
, ValueT
&&value
, TransformT
&&map
)
157 return option_parser::worker(
158 assign
<IntermediateT
>(arg
, std::forward
<TransformT
>(map
)),
159 defaults_to(arg
, map(std::forward
<ValueT
>(value
)))
163 template <typename ArgT
, typename ValueT
>
164 option_parser::worker
assign_default(ArgT
&arg
, ValueT
&&value
)
166 return assign_default
<ArgT
>(arg
, std::forward
<ValueT
>(value
), id_());
169 // workers for specific types
171 option_parser::worker
yes_no(bool &arg
, bool value
);
173 #endif // NCMPCPP_UTILITY_OPTION_PARSER_H