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