BDE 4.39.x Production Release
Loading...
Searching...
No Matches
balb_controlmanager.h
Go to the documentation of this file.
1/// @file balb_controlmanager.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// balb_controlmanager.h -*-C++-*-
8#ifndef INCLUDED_BALB_CONTROLMANAGER
9#define INCLUDED_BALB_CONTROLMANAGER
10
11/// @defgroup balb_controlmanager balb_controlmanager
12/// @brief Provide a mechanism for mapping control messages to callbacks.
13/// @addtogroup bal
14/// @{
15/// @addtogroup balb
16/// @{
17/// @addtogroup balb_controlmanager
18/// @{
19///
20/// <h1> Outline </h1>
21/// * <a href="#balb_controlmanager-purpose"> Purpose</a>
22/// * <a href="#balb_controlmanager-classes"> Classes </a>
23/// * <a href="#balb_controlmanager-description"> Description </a>
24/// * <a href="#balb_controlmanager-callback-function-requirements"> Callback Function Requirements </a>
25/// * <a href="#balb_controlmanager-thread-safety"> Thread Safety </a>
26/// * <a href="#balb_controlmanager-default-handler"> Default Handler </a>
27/// * <a href="#balb_controlmanager-usage"> Usage </a>
28/// * <a href="#balb_controlmanager-example-1-creating-an-echo-message-handler"> Example 1: Creating an ECHO Message Handler </a>
29///
30/// # Purpose {#balb_controlmanager-purpose}
31/// Provide a mechanism for mapping control messages to callbacks.
32///
33/// # Classes {#balb_controlmanager-classes}
34///
35/// - balb::ControlManager: mechanism that maps control messages
36///
37/// # Description {#balb_controlmanager-description}
38/// The `balb::ControlManager` mechanism provided by this component
39/// maps control messages to callback functions on the basis of message
40/// prefixes.
41///
42/// The prefix (case-insensitive) "HELP" is reserved for use by the
43/// `registerUsageHandler`.
44///
45/// ## Callback Function Requirements {#balb_controlmanager-callback-function-requirements}
46///
47///
48/// Functions registered as callbacks for messages must be invokable as
49/// `void(*)(const bsl::string&, bsl::istream&)`. (This signature is
50/// `balb::ControlManager::ControlHandler`). When the function is invoked, the
51/// first argument is the message prefix, and the second is a stream on the
52/// remainder of the message.
53///
54/// ## Thread Safety {#balb_controlmanager-thread-safety}
55///
56///
57/// This component is thread-safe and thread-enabled: it is safe to access and
58/// manipulate multiple distinct instances from different threads, and it is
59/// safe to access and manipulate a single shared instance from different
60/// threads.
61///
62/// ## Default Handler {#balb_controlmanager-default-handler}
63///
64///
65/// The `balb::ControlManager` ignores messages having (case-insensitive)
66/// prefixes that have not been previously registered. Optionally,
67/// users can install a (default) handler for messages messages with
68/// un-registered prefixes. Note that "default" refers to the message prefix --
69/// there is no such handler unless the user explicitly installs one using the
70/// `setDefaultHandler` method.
71///
72/// ## Usage {#balb_controlmanager-usage}
73///
74///
75/// This section illustrates intended use of this component.
76///
77/// ### Example 1: Creating an ECHO Message Handler {#balb_controlmanager-example-1-creating-an-echo-message-handler}
78///
79///
80/// First define a trivial callback to be invoked when an "ECHO" message is
81/// received:
82/// @code
83/// void onEcho(const bsl::string& prefix, bsl::istream& stream)
84/// {
85/// bsl::string word;
86/// bsl::cout << "onEcho: \"" << prefix;
87/// while (stream.good()) {
88/// stream >> word;
89/// bsl::cout << ' ' << word;
90/// }
91/// bsl::cout << '\"' << bsl::endl;
92/// }
93/// @endcode
94/// Now create a `balb::ControlManager` object and register a handler for
95/// "ECHO". Also register a handler for HELP to observe the auto-generated
96/// documentation for ECHO:
97/// @code
98/// balb::ControlManager manager;
99/// manager.registerHandler("ECHO", "<text>",
100/// "Print specified text to the standard output",
101/// &onEcho);
102/// manager.registerHandler("HELP", "",
103/// "Print documentation",
104/// bdlf::BindUtil::bind(
105/// &balb::ControlManager::printUsageHelper,
106/// &manager, &bsl::cout, bsl::string(
107/// "The following commands are accepted by the test driver:")));
108///
109/// manager.dispatchMessage("ECHO repeat this text");
110/// manager.dispatchMessage("echo matching is case-insensitive");
111/// manager.dispatchMessage("HELP");
112/// @endcode
113/// @}
114/** @} */
115/** @} */
116
117/** @addtogroup bal
118 * @{
119 */
120/** @addtogroup balb
121 * @{
122 */
123/** @addtogroup balb_controlmanager
124 * @{
125 */
126
127#include <balscm_version.h>
128
129#include <bslma_allocator.h>
131
133
134#include <bslmt_rwmutex.h>
135
136#include <bsl_functional.h>
137#include <bsl_iosfwd.h>
138#include <bsl_map.h>
139#include <bsl_optional.h>
140#include <bsl_string.h>
141#include <bsl_vector.h>
142
143
144namespace balb {
145
146 // ====================
147 // class ControlManager
148 // ====================
149
150/// Dispatch control messages to callbacks by name.
151///
152/// See @ref balb_controlmanager
154
155 public:
156 // TYPES
157
158 /// Defines a type alias for the function called to handle control
159 /// messages. The `prefix` argument is the first space-delimited word
160 /// read from the message, and the `stream` argument is the
161 /// `bsl::istream` containing the remainder of the message.
162 typedef bsl::function<void(const bsl::string& prefix,
163 bsl::istream& stream)>
165
166 private:
167 // PRIVATE TYPES
168
169 // ==========================
170 // class ControlManager_Entry
171 // ==========================
172
173 // IMPLEMENTATION NOTE: The Sun Studio 12.3 compiler does not support
174 // 'map's holding types that are incomplete at the point of declaration of
175 // a data member. Other compilers allow us to complete
176 // 'ControlManager_Entry' at a later point in the code, but before any
177 // operation (such as 'insert') that would require the type to be complete.
178 // If we did not have to support this compiler, this whole class could be
179 // defined in the .cpp file; as it stands, it *must* be defined before
180 // class 'ControlManager'.
181
182 /// This component-private class represents a function with documentation.
183 ///
184 /// See @ref balb_controlmanager
185 class ControlManager_Entry {
186
187 // DATA
188 ControlManager::ControlHandler d_callback; // processing callback
189 bsl::string d_arguments; // argument description
190 bsl::string d_description; // function description
191
192 public:
193 // TRAITS
194 BSLMF_NESTED_TRAIT_DECLARATION(ControlManager_Entry,
196
197 // CREATORS
198
199 /// Create a `ControlManager_Entry` object. Optionally specify a
200 /// `basicAllocator` used to supply memory. If `basicAllocator` is
201 /// 0, the currently installed default allocator is used.
202 explicit ControlManager_Entry(bslma::Allocator *basicAllocator = 0);
203
204 /// Create an `ControlManager_Entry` object with the specified initial
205 /// values.
206 ControlManager_Entry(
207 const ControlManager::ControlHandler& callback,
208 const bsl::string_view& arguments,
209 const bsl::string_view& description,
210 bslma::Allocator *basicAllocator = 0);
211
212 /// Create an `ControlManager_Entry` object having the value of the
213 /// specified `original` object. Optionally specify a
214 /// `basicAllocator` used to supply memory. If `basicAllocator` is
215 /// 0, the currently installed default allocator is used.
216 ControlManager_Entry(const ControlManager_Entry& original,
217 bslma::Allocator *basicAllocator = 0);
218
219 /// Destroy this object.
220 ~ControlManager_Entry();
221
222 // MANIPULATORS
223
224 /// Assign to this object the value of the specified `rhs` object.
225 ControlManager_Entry& operator=(const ControlManager_Entry& rhs);
226
227 /// Set the specified `callback` as the value of the `callback`
228 /// member of this object.
229 void setCallback(const ControlManager::ControlHandler& callback);
230
231 /// Return a modifiable reference to the `arguments` member of this
232 /// object.
233 bsl::string& arguments();
234
235 /// Return a modifiable reference to the `description` member of
236 /// this object.
237 bsl::string& description();
238
239 // ACCESSORS
240
241 /// Return a non-modifiable reference to the `callback` member of
242 /// this object.
243 const ControlManager::ControlHandler& callback() const;
244
245 /// Return a non-modifiable reference to the `arguments` member of
246 /// this object.
247 const bsl::string& arguments() const;
248
249 /// Return a non-modifiable reference to the `arguments` member of
250 /// this object.
251 const bsl::string& description() const;
252 };
253
254 struct CaselessLessThan {
255 // TYPES
256 typedef void is_transparent;
257
258 // ACCESSOR
259
260 /// Return `true` if the specified `lhs` is less than the specified
261 /// `rhs` in a case-insensitive comparison, and `false` otherwise.
262 bool operator()(const bsl::string_view& lhs,
263 const bsl::string_view& rhs) const;
264 };
265
266 /// Defines a type alias for the ordered associative data structure that
267 /// maps a message prefix to a `StringComparator` functor.
269 Registry;
270
271 // DATA
272 bslma::Allocator *d_allocator_p; // memory allocator (held)
273
274 Registry d_registry; // registry
275
276 mutable bslmt::RWMutex d_registryMutex; // mutex for registry
277 // and default handler
278
279 bsl::optional<ControlHandler> d_defaultHandler; // default handler
280
281 private:
282 // NOT IMPLEMENTED
283 ControlManager(const ControlManager&); // = deleted
284 ControlManager& operator=(const ControlManager&); // = deleted
285
286 public:
287 // TRAITS
289
290 // CREATORS
291
292 /// Create a control manager object. Optionally specify a
293 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
294 /// the currently installed default allocator is used.
295 explicit ControlManager(bslma::Allocator *basicAllocator = 0);
296
297 /// Destroy this object.
299
300 // MANIPULATORS
301
302 /// Register the specified `handler` to be invoked whenever a control
303 /// message having the specified case-insensitive `prefix` is received
304 /// by this control manager. Also register the specified `arguments`
305 /// string to describe the arguments accepted by the message, and the
306 /// specified `description` to describe its operation; these are printed
307 /// by `printUsage`. Return a positive value if an existing callback
308 /// was replaced, return 0 if no replacement occurred, and return a
309 /// negative value otherwise.
311 const bsl::string_view& arguments,
312 const bsl::string_view& description,
313 const ControlHandler& handler);
314
315 /// Register a handler that, on receipt of a (case-insensitive) "HELP"
316 /// message, prints to the specified stream a list of this
317 /// `ControlManager`s registered commands and their documentation.
318 /// Return a positive value if an existing callback was replaced, return
319 /// 0 if no replacement occurred, and return a negative value otherwise.
320 int registerUsageHandler(bsl::ostream& stream);
321
322 /// Register the specified `handler` to be invoked whenever a control
323 /// message having an unregistered (case-insensitive) `prefix` is received
324 /// by this control manager. Return a positive value if an existing
325 /// callback was replaced, return 0 if no replacement occurred, and return
326 /// a negative value otherwise.
328
329 /// Deregister the callback function previously registered to handle the
330 /// specified `prefix`. Return 0 on success or a non-zero value
331 /// otherwise.
333
334 // Deregister the callback function previously registered to handle "HELP"
335 // messages (see `registerUsageHandler`). Return 0 on success or a
336 // non-zero value otherwise.
338
339 /// Deregister the callback function previously registered (see
340 /// `registerDefaultHandler`) to handle messages with unregistered
341 /// prefixes. Return 0 on success or a non-zero value otherwise.
343
344 // ACCESSOR
345
346 /// Parse the specified complete `message` and dispatch it. Return
347 /// 0 on success, and a non-zero value otherwise; in particular return
348 /// non-zero if no registered callback could be found for the
349 /// case-insensitive prefix in `message` and no default handler is
350 /// installed.
351 int dispatchMessage(const bsl::string_view& message) const;
352
353 /// Dispatch the message contained in the specified `stream` to the
354 /// callback associated with the specified `prefix`. Return 0 on
355 /// success, and a non-zero value otherwise; in particular return
356 /// non-zero if no registered callback could be found for the
357 /// case-insensitive `prefix` and no default handler is installed.
358 int dispatchMessage(const bsl::string& prefix, bsl::istream& stream) const;
359
360 /// Return `true` if this control manager has a default message handler
361 /// installed, and `false` otherwise.
362 bool hasDefaultHandler() const;
363
364 /// Print to the specified `stream` the specified `preamble` text,
365 /// followed by the registered commands and documentation for this control manager.
366 ///
367 /// \note Note that a newline is appended to `preamble` in
368 /// the output.
369 void printUsage(bsl::ostream& stream,
370 const bsl::string_view& preamble) const;
371
372 /// Invoke `printUsage` passing the specified `*stream` and `preamble`.
373 /// Suitable for binding using the bdlf::BindUtil package.
374 void printUsageHelper(bsl::ostream *stream,
375 const bsl::string_view& preamble) const;
376
377 // Aspects
378
379 /// Return the allocator used by this object to supply memory.
380 ///
381 /// \note Note that if no allocator was supplied at construction the default
382 /// allocator in effect at construction is used.
384};
385
386// ============================================================================
387// INLINE DEFINITIONS
388// ============================================================================
389
390 // ------------------------------------------
391 // class ControlManager::ControlManager_Entry
392 // ------------------------------------------
393
394// MANIPULATORS
395inline
396void ControlManager::ControlManager_Entry::setCallback(
397 const ControlManager::ControlHandler& callback)
398{
399 d_callback = callback;
400}
401
402inline
403bsl::string& ControlManager::ControlManager_Entry::arguments()
404{
405 return d_arguments;
406}
407
408inline
409bsl::string& ControlManager::ControlManager_Entry::description()
410{
411 return d_description;
412}
413
414// ACCESSORS
415inline
417ControlManager::ControlManager_Entry::callback() const
418{
419 return d_callback;
420}
421
422inline
423const bsl::string& ControlManager::ControlManager_Entry::arguments() const
424{
425 return d_arguments;
426}
427
428inline
429const bsl::string& ControlManager::ControlManager_Entry::description() const
430{
431 return d_description;
432}
433
434 // --------------------
435 // class ControlManager
436 // --------------------
437
438// MANIPULATORS
439inline
444
445// ACCESSORS
446
447inline
448void ControlManager::printUsageHelper(bsl::ostream *stream,
449 const bsl::string_view& preamble) const
450{
451 printUsage(*stream, preamble);
452}
453
454 // Aspects
455
456inline
458{
459 return d_allocator_p;
460}
461
462} // close package namespace
463
464
465#endif
466
467// ----------------------------------------------------------------------------
468// Copyright 2015 Bloomberg Finance L.P.
469//
470// Licensed under the Apache License, Version 2.0 (the "License");
471// you may not use this file except in compliance with the License.
472// You may obtain a copy of the License at
473//
474// http://www.apache.org/licenses/LICENSE-2.0
475//
476// Unless required by applicable law or agreed to in writing, software
477// distributed under the License is distributed on an "AS IS" BASIS,
478// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
479// See the License for the specific language governing permissions and
480// limitations under the License.
481// ----------------------------- END-OF-FILE ----------------------------------
482
483/** @} */
484/** @} */
485/** @} */
#define BSLMF_NESTED_TRAIT_DECLARATION(t_TYPE, t_TRAIT)
Definition bslmf_nestedtraitdeclaration.h:231
Definition balb_controlmanager.h:153
BSLMF_NESTED_TRAIT_DECLARATION(ControlManager, bslma::UsesBslmaAllocator)
bslma::Allocator * allocator() const
Definition balb_controlmanager.h:457
int deregisterUsageHandler()
Definition balb_controlmanager.h:440
~ControlManager()
Destroy this object.
ControlManager(bslma::Allocator *basicAllocator=0)
bsl::function< void(const bsl::string &prefix, bsl::istream &stream)> ControlHandler
Definition balb_controlmanager.h:164
int deregisterHandler(const bsl::string_view &prefix)
int registerUsageHandler(bsl::ostream &stream)
void printUsageHelper(bsl::ostream *stream, const bsl::string_view &preamble) const
Definition balb_controlmanager.h:448
bool hasDefaultHandler() const
int registerDefaultHandler(const ControlHandler &hander)
int dispatchMessage(const bsl::string_view &message) const
int dispatchMessage(const bsl::string &prefix, bsl::istream &stream) const
void printUsage(bsl::ostream &stream, const bsl::string_view &preamble) const
int registerHandler(const bsl::string_view &prefix, const bsl::string_view &arguments, const bsl::string_view &description, const ControlHandler &handler)
Definition bslstl_stringview.h:471
Definition bslstl_string.h:1252
Forward declaration.
Definition bslstl_function.h:946
Definition bslstl_map.h:653
Definition bslstl_optional.h:2043
Definition bslma_allocator.h:545
Definition bslmt_rwmutex.h:148
Definition balb_controlmanager.h:144
Definition bslma_usesbslmaallocator.h:344