E-MailRelay
goptionmap.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 goptionmap.cpp
19///
20
21#include "gdef.h"
22#include "goptionmap.h"
23#include "gstringfield.h"
24#include "gassert.h"
25#include <algorithm>
26
27void G::OptionMap::insert( const Map::value_type & value )
28{
29 m_map.insert( value ) ;
30}
31
32G::OptionMap::Range G::OptionMap::findRange( std::string_view key ) const noexcept
33{
34 // 'generic associative lookup' is c++14 and c++11 equal_range()
35 // is not noexcept, so do it ourselves
36 auto first = std::find_if( m_map.cbegin() , m_map.cend() ,
37 [key](const Map::value_type & v_){return key == v_.first ;} ) ;
38 auto second = std::find_if( first , m_map.cend() ,
39 [key](const Map::value_type & v_){return key != v_.first ;} ) ;
40 return {first,second} ;
41}
42
43G::OptionMap::Map::iterator G::OptionMap::findFirst( std::string_view key ) noexcept
44{
45 // as above
46 auto result = std::find_if( m_map.begin() , m_map.end() ,
47 [key](const Map::value_type & v_){return key == v_.first ;} ) ;
48 G_ASSERT( result == m_map.find(sv_to_string(key)) ) ;
49 return result ;
50}
51
52G::OptionMap::const_iterator G::OptionMap::find( std::string_view key ) const noexcept
53{
54 auto pair = findRange( key ) ;
55 return pair.first == pair.second ? m_map.end() : pair.first ;
56}
57
58void G::OptionMap::replace( std::string_view key , const std::string & value )
59{
60 auto pair = findRange( key ) ;
61 if( pair.first != pair.second )
62 m_map.erase( pair.first , pair.second ) ;
63 m_map.insert( Map::value_type(sv_to_string(key),OptionValue(value)) ) ;
64}
65
66void G::OptionMap::increment( std::string_view key ) noexcept
67{
68 auto p = findFirst( key ) ;
69 if( p != m_map.end() )
70 {
71 Map::value_type & value = *p ;
72 value.second.increment() ;
73 }
74}
75
76G::OptionMap::const_iterator G::OptionMap::begin() const noexcept
77{
78 return m_map.cbegin() ;
79}
80
81#ifndef G_LIB_SMALL
82G::OptionMap::const_iterator G::OptionMap::cbegin() const noexcept
83{
84 return begin() ;
85}
86#endif
87
88G::OptionMap::const_iterator G::OptionMap::end() const noexcept
89{
90 return m_map.cend() ;
91}
92
93#ifndef G_LIB_SMALL
94G::OptionMap::const_iterator G::OptionMap::cend() const noexcept
95{
96 return end() ;
97}
98#endif
99
101{
102 m_map.clear() ;
103}
104
105bool G::OptionMap::contains( std::string_view key ) const noexcept
106{
107 auto range = findRange( key ) ;
108 for( auto p = range.first ; p != range.second ; ++p )
109 {
110 if( (*p).second.isOff() )
111 continue ;
112 return true ;
113 }
114 return false ;
115}
116
117bool G::OptionMap::contains( const char * key ) const noexcept
118{
119 return contains( std::string_view(key) ) ;
120}
121
122bool G::OptionMap::contains( const std::string & key ) const noexcept
123{
124 return contains( std::string_view(key) ) ;
125}
126
127std::size_t G::OptionMap::count( std::string_view key ) const noexcept
128{
129 std::size_t n = 0U ;
130 auto pair = findRange( key ) ;
131 for( auto p = pair.first ; p != pair.second ; ++p )
132 n += (*p).second.count() ;
133 return n ;
134}
135
136std::string G::OptionMap::value( std::string_view key , std::string_view default_ ) const
137{
138 auto range = findRange( key ) ;
139 if( range.first == range.second )
140 return sv_to_string(default_) ;
141 else
142 return join( range.first , range.second , default_ ) ;
143}
144
145std::string G::OptionMap::join( Map::const_iterator p , Map::const_iterator end , std::string_view off_value )
146{
147 std::string result ;
148 const char * sep = "" ;
149 for( ; p != end ; ++p )
150 {
151 result.append( sep ) ; sep = "," ;
152 result.append( (*p).second.value() ) ;
153 if( (*p).second.isOn() )
154 return (*p).second.value() ;
155 if( (*p).second.isOff() )
156 return sv_to_string(off_value) ;
157 }
158 return result ;
159}
160
161unsigned int G::OptionMap::number( std::string_view key , unsigned int default_ ) const noexcept
162{
163 G_ASSERT( !G::Str::isUInt("") ) ;
164 auto p = find( key ) ;
165 if( p == m_map.end() )
166 {
167 return default_ ;
168 }
169 else
170 {
171 static_assert( std::is_same<decltype(*p),const Map::value_type&>::value , "" ) ;
172 //static_assert( noexcept(*p) , "" ) ; // not declared noexcept by msvc
173 const Map::value_type & value = *p ; // noexcept in practice
174 return G::Str::toUInt( value.second.valueref() , default_ ) ;
175 }
176}
177
const_iterator find(std::string_view) const noexcept
Finds the map entry with the given key.
Definition: goptionmap.cpp:52
const_iterator begin() const noexcept
Returns the begin iterator.
Definition: goptionmap.cpp:76
void increment(std::string_view key) noexcept
Increments the repeat count for the given entry.
Definition: goptionmap.cpp:66
void replace(std::string_view key, const std::string &value)
Replaces all matching values with a single value.
Definition: goptionmap.cpp:58
const_iterator cend() const noexcept
Returns the off-the-end iterator.
Definition: goptionmap.cpp:94
const_iterator end() const noexcept
Returns the off-the-end iterator.
Definition: goptionmap.cpp:88
bool contains(std::string_view) const noexcept
Returns true if the map contains the given key, but ignoring 'off' option-values.
Definition: goptionmap.cpp:105
const_iterator cbegin() const noexcept
Returns the begin iterator.
Definition: goptionmap.cpp:82
unsigned int number(std::string_view key, unsigned int default_) const noexcept
Returns the matching value as a number.
Definition: goptionmap.cpp:161
void clear()
Clears the map.
Definition: goptionmap.cpp:100
std::string value(std::string_view key, std::string_view default_={}) const
Returns the matching value, with concatentation into a comma-separated list if multivalued (with no e...
Definition: goptionmap.cpp:136
std::size_t count(std::string_view key) const noexcept
Returns the total repeat count for all matching entries.
Definition: goptionmap.cpp:127
void insert(const Map::value_type &)
Inserts the key/value pair into the map.
Definition: goptionmap.cpp:27
A simple structure encapsulating the value of a command-line option.
Definition: goptionvalue.h:40
static bool isUInt(std::string_view s) noexcept
Returns true if the string can be converted into an unsigned integer without throwing an exception.
Definition: gstr.cpp:446
static unsigned int toUInt(std::string_view s)
Converts string 's' to an unsigned int.
Definition: gstr.cpp:648