Options.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 #include "squid.h"
10 #include "acl/Options.h"
11 #include "ConfigParser.h"
12 #include "Debug.h"
13 #include "sbuf/Stream.h"
14 
15 #include <iostream>
16 #include <vector>
17 
18 namespace Acl {
19 
22 {
23 public:
26  bool extractOne();
27 
28  /* extracted option details (after successful extraction */
30  bool hasValue = false;
31  const SBuf &value() const;
32 
33 protected:
34  bool advance();
35  void extractWhole();
36  void extractShort();
37 
38 private:
42  bool sawValue_ = false;
43 };
44 
47 {
48 public:
49  OptionsParser(const Options &options, const ParameterFlags &flags);
50 
51  // fill previously supplied options container, throwing on errors
52  void parse();
53 
54 private:
55  const Option *findOption(/* const */ SBuf &rawName);
56 
58  typedef std::vector<OptionName> Names;
61 
62  const Options &options_;
64 };
65 
66 } // namespace Acl
67 
68 /* Acl::OptionNameCmp */
69 
70 bool
72 {
73  return strcmp(a, b) < 0;
74 }
75 
76 /* Acl::OptionExtractor */
77 
78 const SBuf &
80 {
81  Must(hasValue);
82  return value_;
83 }
84 
85 bool
87 {
88  if (!prefix_.isEmpty()) {
89  extractShort(); // continue with the previously extracted flags
90  return true;
91  }
92 
93  if (!advance())
94  return false; // end of options (and, possibly, the whole "acl" directive)
95 
96  if (prefix_.length() < 2)
97  throw TexcHere(ToSBuf("truncated(?) ACL flag: ", prefix_)); // single - or +
98 
99  if (prefix_[0] == '-' && prefix_[1] == '-') {
100  if (prefix_.length() == 2)
101  return false; // skipped "--", an explicit end-of-options marker
102  extractWhole();
103  return true;
104  }
105 
106  if (prefix_.length() == 2) { // common trivial case: -x or +y
107  extractWhole();
108  return true;
109  }
110 
111  // -xyz or +xyz
112  letterPos_ = 1;
113  extractShort();
114  return true;
115 }
116 
118 bool
120 {
121  const char *next = ConfigParser::PeekAtToken();
122  if (!next)
123  return false; // end of the "acl" line
124 
125  const char nextChar = *next;
126  if (!(nextChar == '-' || nextChar == '+'))
127  return false; // start of ACL parameters
128 
129  sawValue_ = strchr(next, '='); // TODO: Make ConfigParser reject '^=.*' tokens
130  if (sawValue_) {
131  char *rawPrefix = nullptr;
132  char *rawValue = nullptr;
133  if (!ConfigParser::NextKvPair(rawPrefix, rawValue))
134  throw TexcHere(ToSBuf("Malformed acl option=value: ", next));
135  prefix_.assign(rawPrefix);
136  value_.assign(rawValue);
137  } else {
138  prefix_.assign(next);
139  ConfigParser::NextToken(); // consume what we have peeked at
140  }
141  return true;
142 }
143 
145 void
147 {
148  debugs(28, 8, "from " << prefix_ << " value: " << sawValue_);
149  hasValue = sawValue_;
150  name = prefix_;
151  prefix_.clear();
152 }
153 
155 void
157 {
158  debugs(28, 8, "from " << prefix_ << " at " << letterPos_ << " value: " << sawValue_);
159  name.assign(prefix_.rawContent(), 1); // leading - or +
160  name.append(prefix_.at(letterPos_++));
161  if (letterPos_ >= prefix_.length()) { // got last flag in the sequence
162  hasValue = sawValue_;
163  prefix_.clear();
164  } else {
165  hasValue = false;
166  }
167 }
168 
169 /* Acl::OptionsParser */
170 
171 // being "static" is an optimization to avoid paying for vector creation/growth
173 
175  options_(options),
176  parameterFlags_(flags)
177 {
178 }
179 
180 const Acl::Option *
181 Acl::OptionsParser::findOption(/* const */ SBuf &rawNameBuf)
182 {
183  // TODO: new std::map::find() in C++14 does not require this conversion
184  const auto rawName = rawNameBuf.c_str();
185 
186  const auto optionPos = options_.find(rawName);
187  if (optionPos != options_.end())
188  return optionPos->second;
189 
190  const auto flagPos = parameterFlags_.find(rawName);
191  if (flagPos != parameterFlags_.end()) {
192  flagsToSkip.push_back(*flagPos); // *flagPos is permanent unlike rawName
193  return nullptr;
194  }
195 
196  throw TexcHere(ToSBuf("unsupported ACL option: ", rawNameBuf));
197 }
198 
199 void
201 {
202  flagsToSkip.clear();
203 
204  OptionExtractor oex;
205  while (oex.extractOne()) {
206  /* const */ auto rawName = oex.name;
207  if (const Option *optionPtr = findOption(rawName)) {
208  const Option &option = *optionPtr;
209  if (option.configured())
210  debugs(28, 7, "acl uses multiple " << rawName << " options");
211  switch (option.valueExpectation)
212  {
213  case Option::valueNone:
214  if (oex.hasValue)
215  throw TexcHere(ToSBuf("unexpected value for an ACL option: ", rawName, '=', oex.value()));
216  option.configureDefault();
217  break;
219  if (!oex.hasValue)
220  throw TexcHere(ToSBuf("missing required value for ACL option ", rawName));
221  option.configureWith(oex.value());
222  break;
224  if (oex.hasValue)
225  option.configureWith(oex.value());
226  else
227  option.configureDefault();
228  break;
229  }
230  }
231  // else skip supported parameter flag
232  }
233 
234  /* hack: regex code wants to parse all -i and +i flags itself */
235  for (const auto name: flagsToSkip)
237 }
238 
239 void
240 Acl::ParseFlags(const Options &options, const ParameterFlags &flags)
241 {
242  OptionsParser parser(options, flags);
243  parser.parse();
244 }
245 
246 const Acl::Options &
248 {
249  static const Options none = {};
250  return none;
251 }
252 
253 const Acl::ParameterFlags &
255 {
256  static const ParameterFlags none = {};
257  return none;
258 }
259 
260 std::ostream &
261 operator <<(std::ostream &os, const Acl::Option &option)
262 {
263  if (option.valued()) {
264  os << '=';
265  option.print(os);
266  }
267  return os;
268 }
269 
270 std::ostream &
271 operator <<(std::ostream &os, const Acl::Options &options)
272 {
273  for (const auto pos: options) {
274  assert(pos.second);
275  const auto &option = *pos.second;
276  if (option.configured())
277  os << pos.first << option;
278  }
279  // TODO: Remember "--" presence and print that delimiter when present.
280  // Detecting its need is difficult because parameter flags start with "-".
281  return os;
282 }
283 
SBuf name
extracted option name, including dash(es)
Definition: Options.cc:29
bool advance()
extracts a token with the next option/flag(s) or returns false
Definition: Options.cc:119
#define assert(EX)
Definition: assert.h:17
bool sawValue_
the current option sequence had a value
Definition: Options.cc:42
ValueExpectation valueExpectation
expect "=value" part?
Definition: Options.h:61
Definition: SBuf.h:87
SBuf::size_type letterPos_
letter position inside an -xyz sequence
Definition: Options.cc:41
void extractShort()
handles one flag letter inside an -xyx[=option] or +xyz[=option] sequence
Definition: Options.cc:156
const SBuf & value() const
extracted option value (requires hasValue)
Definition: Options.cc:79
std::vector< OptionName > Names
ACL parameter flags in parsing order.
Definition: Options.cc:58
static char * PeekAtToken()
static void TokenPutBack(const char *token)
Definition: ConfigParser.cc:61
virtual bool configured() const =0
virtual void configureWith(const SBuf &rawValue) const =0
called after parsing -x=value or –name=value
bool operator()(const OptionName a, const OptionName b) const
Definition: Options.cc:71
virtual bool valued() const =0
const ParameterFlags & NoFlags()
Definition: Options.cc:254
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
void ParseFlags(const Options &options, const ParameterFlags &flags)
Definition: Options.cc:240
const Options & options_
caller-supported, linked options
Definition: Options.cc:62
const ParameterFlags & parameterFlags_
caller-supported parameter flags
Definition: Options.cc:63
static char * NextToken()
const Option * findOption(SBuf &rawName)
Definition: Options.cc:181
virtual void print(std::ostream &os) const =0
prints a configuration snippet (as an admin could have typed)
bool hasValue
whether the option has a value (-x=value)
Definition: Options.cc:30
void extractWhole()
handles -x[=option] or –foo[=option]
Definition: Options.cc:146
const char * c_str()
Definition: SBuf.cc:546
parses/validates/stores ACL options; skips/preserves parameter flags
Definition: Options.cc:46
static Names flagsToSkip
parsed ACL parameter flags that must be preserved for ACLData::parse()
Definition: Options.cc:60
#define Must(cond)
Definition: TextException.h:89
std::set< OptionName, OptionNameCmp > ParameterFlags
a set of parameter flag names
Definition: Options.h:162
OptionsParser(const Options &options, const ParameterFlags &flags)
Definition: Options.cc:174
SBuf ToSBuf(Args &&...args)
slowly stream-prints all arguments into a freshly allocated SBuf
Definition: Stream.h:124
virtual void configureDefault() const =0
called after parsing -x or –name
static bool NextKvPair(char *&key, char *&value)
std::map< OptionName, const Option *, OptionNameCmp > Options
name:option map
Definition: Options.h:159
#define TexcHere(msg)
Definition: TextException.h:81
low-level parser that extracts but does not interpret ACL options
Definition: Options.cc:21
std::ostream & operator<<(std::ostream &os, const Acl::Option &option)
Definition: Options.cc:261
int a
Definition: membanger.c:50
SBuf value_
the last seen value of some option
Definition: Options.cc:40
MemBlob::size_type size_type
Definition: SBuf.h:90
const Options & NoOptions()
Definition: Options.cc:247
SBuf prefix_
option name(s), including leading dash(es)
Definition: Options.cc:39
const char * OptionName
Definition: Options.h:35

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors