E-MailRelay
goptions.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file goptions.cpp
19///
20
21#include "gdef.h"
22#include "gstr.h"
23#include "ggettext.h"
24#include "goptions.h"
25#include <algorithm>
26
28= default;
29
30G::Options::Options( const std::string & spec , char sep_major , char sep_minor , char escape )
31{
32 parseSpec( spec , sep_major , sep_minor , escape ) ;
33}
34
35void G::Options::parseSpec( const std::string & spec , char sep_major , char sep_minor , char escape )
36{
37 // split into separate options
38 StringArray spec_items ;
39 spec_items.reserve( 40U ) ;
40 Str::splitIntoFields( spec , spec_items , sep_major , escape , false ) ;
41
42 // for each option
43 for( auto & spec_item : spec_items )
44 {
45 // split into separate fields
46 if( spec_item.empty() ) continue ;
47 StringArray inner_parts ;
48 inner_parts.reserve( 10U ) ;
49 Str::splitIntoFields( spec_item , inner_parts , sep_minor , escape ) ;
50
51 if( inner_parts.size() < 7U )
52 throw InvalidSpecification( std::string(1U,'[').append(G::Str::join(",",inner_parts)).append(1U,']') ) ;
53
54 std::string short_form = inner_parts[0] ;
55 char c = short_form.empty() ? '\0' : short_form[0U] ;
56 unsigned int level = Str::toUInt( inner_parts[6U] ) ;
57
58 Option::Multiplicity multiplicity = Option::decode( inner_parts[4U] ) ;
59 if( multiplicity == Option::Multiplicity::error )
60 throw InvalidSpecification( std::string(1U,'[').append(G::Str::join(",",inner_parts)).append(1U,']') ) ;
61
62 Option opt( c , inner_parts[1U] , inner_parts[2U] , inner_parts[3U] ,
63 multiplicity , inner_parts[5U] , level ) ;
64
65 addOption( opt , sep_minor , escape ) ;
66 }
67}
68
69void G::Options::add( Options & options , char c , const char * name , const char * text ,
70 const char * more , Option::Multiplicity m , const char * argname ,
71 unsigned int level , unsigned int main_tag , unsigned int tag_bits )
72{
73 options.add( Option(c,name,G::gettext(text),more,m,argname,level,main_tag,main_tag|tag_bits) ) ;
74}
75
76void G::Options::add( const Option & opt , char sep , char escape )
77{
78 addOption( opt , sep , escape ) ;
79}
80
81void G::Options::addOption( Option opt , char sep , char escape )
82{
83 if( sep )
84 {
85 // if the description is in two parts separated by 'sep' and the
86 // extra-description is empty then take the first half as the
87 // description and the second part as the extra-description -- this
88 // allows the description to be translatable as a single string
89 //
90 StringArray sub_parts ;
91 sub_parts.reserve( 2U ) ;
92 Str::splitIntoFields( opt.description , sub_parts , sep , escape ) ;
93 if( sub_parts.size() > 2U || ( sub_parts.size()==2U && !opt.description_extra.empty() ) )
94 throw InvalidSpecification() ;
95 if( sub_parts.size() == 2U )
96 {
97 opt.description = sub_parts[0] ;
98 opt.description_extra = sub_parts[1] ;
99 }
100 }
101
102 auto range = std::equal_range( m_list.begin() , m_list.end() , opt ,
103 [](const Option & a, const Option & b){ return a.name < b.name ; } ) ;
104
105 if( range.first != range.second )
106 throw InvalidSpecification( "duplication" ) ;
107
108 m_list.insert( range.first , opt ) ;
109}
110
111bool G::Options::defaulting( char c ) const
112{
113 return defaulting( lookup(c) ) ;
114}
115
116bool G::Options::defaulting( const std::string & name ) const
117{
118 const Option * p = find( name ) ;
119 return p ? p->defaulting() : false ;
120}
121
122bool G::Options::valued( char c ) const
123{
124 return valued( lookup(c) ) ;
125}
126
127bool G::Options::valued( const std::string & name ) const
128{
129 const Option * p = find( name ) ;
130 return p ? p->valued() : false ;
131}
132
133bool G::Options::unvalued( const std::string & name ) const
134{
135 return valid(name) && !valued(name) ;
136}
137
138bool G::Options::multivalued( char c ) const
139{
140 return multivalued( lookup(c) ) ;
141}
142
143bool G::Options::multivalued( const std::string & name ) const
144{
145 const Option * p = find( name ) ;
146 return p ? p->multivalued() : false ;
147}
148
149bool G::Options::visible( const std::string & name , unsigned int level , bool level_exact ) const
150{
151 const Option * p = find( name ) ;
152 return p ? p->visible({level_exact?level:1U,level}) : false ;
153}
154
155bool G::Options::visible( const std::string & name ) const
156{
157 return visible( name , 99U , false ) ;
158}
159
160bool G::Options::valid( const std::string & name ) const
161{
162 return find(name) != nullptr ;
163}
164
165std::string G::Options::lookup( char c ) const
166{
167 for( auto p = m_list.begin() ; c != '\0' && p != m_list.end() ; ++p )
168 {
169 if( (*p).c == c )
170 return (*p).name ;
171 }
172 return {} ;
173}
174
175const G::Option * G::Options::find( const std::string & name ) const
176{
177 for( const auto & option : m_list )
178 {
179 if( option.name == name )
180 return &option ;
181 }
182 return nullptr ;
183}
184
185const std::vector<G::Option> & G::Options::list() const
186{
187 return m_list ;
188}
189
A class to assemble a list of command-line options and provide access by name.
Definition: goptions.h:40
std::string lookup(char c) const
Converts from short-form option character to the corresponding long-form name.
Definition: goptions.cpp:165
bool unvalued(const std::string &) const
Returns true if the given option name is valid and takes no value.
Definition: goptions.cpp:133
static void add(Options &, char c, const char *name, const char *text, const char *more, Option::Multiplicity m, const char *argname, unsigned int level, unsigned int main_tag_bit, unsigned int tag_bits=0U)
A convenience function that constructs an Option object with the trailing arguments and then calls ad...
Definition: goptions.cpp:69
bool visible(const std::string &name, unsigned int level, bool level_exact=false) const
Returns true if the option is visible at the given level.
Definition: goptions.cpp:149
bool defaulting(const std::string &) const
Returns true if the given long-form single-valued() option can optionally have no explicit value,...
Definition: goptions.cpp:116
bool valid(const std::string &) const
Returns true if the long-form option name is valid.
Definition: goptions.cpp:160
bool multivalued(char) const
Returns true if the short-form option can have multiple values.
Definition: goptions.cpp:138
bool valued(char) const
Returns true if the given short-form option takes a value, Returns true if the short-form option char...
Definition: goptions.cpp:122
const Option * find(const std::string &) const
Returns a pointer to the option with a matching long-form name.
Definition: goptions.cpp:175
Options()
Default constructor for no options.
const std::vector< Option > & list() const
Returns the sorted list of option structures.
Definition: goptions.cpp:185
static std::string join(std::string_view sep, const StringArray &strings)
Concatenates an array of strings with separators.
Definition: gstr.cpp:1221
static void splitIntoFields(std::string_view in, StringArray &out, char sep, char escape='\0', bool remove_escapes=true)
Splits the string into fields.
Definition: gstr.cpp:1191
static unsigned int toUInt(std::string_view s)
Converts string 's' to an unsigned int.
Definition: gstr.cpp:648
const char * gettext(const char *) noexcept
Returns the message translation in the current locale's codeset, eg.
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstringarray.h:30
A structure representing a G::Options command-line option.
Definition: goption.h:38
static Multiplicity decode(const std::string &)
Decodes a multiplicity string into its enumeration.
Definition: goption.cpp:57