📄 handlercall.hh
字号:
// -*- c-basic-offset: 4; related-file-name: "../../lib/handlercall.cc" -*-#ifndef CLICK_HANDLERCALL_HH#define CLICK_HANDLERCALL_HH#include <click/router.hh>CLICK_DECLSclass VariableExpander;/** @brief Convenience class for calling handlers. * * The HandlerCall class simplifies the process of calling Click handlers. * (The lower-level interface is the Handler class.) HandlerCall is used in * two ways: (1) to call handlers immediately via static member functions, * and (2) to set up future handler calls via HandlerCall objects. The * immediate handler call functions take handler names as arguments and * perform all necessary error checks before calling handlers, if any. A * HandlerCall object encapsulates a handler reference (possibly including * parameters), again automating all necessary error checks. * * <h2>Immediate Handler Calls</h2> * * This example code shows how to use the HandlerCall functions for calling * handlers immediately. * * @code * class YourElement { ... * Element *_other; * } * * void YourElement::function() { * // Call _other's "config" read handler. * String result = HandlerCall::call_read(_other, "config"); * * // The same, providing an error handler to print errors. * ErrorHandler *errh = ErrorHandler::default_handler(); * result = HandlerCall::call_read(_other, "config", errh); * // (Each function takes an optional last argument of "errh".) * * // Call the "foo.config" read handler. Search for element "foo" in * // the current compound element context. * result = HandlerCall::call_read("foo.config", this); * * // Call the global "config" read handler for the current router. * result = HandlerCall::call_read("config", this); * * // Call _other's "stop" write handler with empty value. * int success = HandlerCall::call_write(_other, "stop"); * * // Call _other's "config" write handler with value "blah". * success = HandlerCall::call_write(_other, "config", "blah"); * * // Call the "foo.config" write handler with value "blah". * success = HandlerCall::call_write("foo.config blah", this); * // Or, alternately: * success = HandlerCall::call_write("foo.config", "blah", this); * } * @endcode * * <h2>HandlerCall Objects</h2> * * This example code shows how to use the HandlerCall objects to call * handlers with simplified error checking. * * @code * class YourElement { ... * HandlerCall _read_call; * HandlerCall _write_call; * } * * YourElement::YourElement() * : _read_call(), _write_call() { * } * * int YourElement::configure(Vector<String> &conf, ErrorHandler *errh) { * return cp_va_kparse(conf, this, errh, * "READ_CALL", cpkP, cpHandlerCallRead, &_read_call, * "WRITE_CALL", cpkP, cpHandlerCallWrite, &_write_call, * cpEnd); * } * * int YourElement::initialize(ErrorHandler *errh) { * if ((_read_call && _read_call.initialize_read(this, errh) < 0) * || (_write_call && _write_call.initialize_write(this, errh) < 0)) * return -1; * return 0; * } * * void YourElement::function() { * // call _read_call, print result * if (_read_call) * click_chatter("%s", _read_call.call_read()); * * // call _write_call with error handler * if (_write_call) * _write_call.call_write(ErrorHandler::default_handler()); * } * @endcode * * If usually your element's handler calls aren't used, you can save a small * amount of space by using pointers to HandlerCall objects, as in this * example. The cpHandlerCallPtrRead and cpHandlerCallPtrWrite types allow * the _read_call and _write_call members to start out as null pointers. * * @code * class YourElement { ... * HandlerCall *_read_call; * HandlerCall *_write_call; * } * * YourElement::YourElement() * : _read_call(0), _write_call(0) { * } * * int YourElement::configure(Vector<String> &conf, ErrorHandler *errh) { * return cp_va_kparse(conf, this, errh, * "READ_CALL", cpkP, cpHandlerCallPtrRead, &_read_call, * "WRITE_CALL", cpkP, cpHandlerCallPtrWrite, &_write_call, * cpEnd); * } * * int YourElement::initialize(ErrorHandler *errh) { * if ((_read_call && _read_call->initialize_read(this, errh) < 0) * || (_write_call && _write_call->initialize_write(this, errh) < 0)) * return -1; * return 0; * } * * void YourElement::cleanup(CleanupStage) { * delete _read_call; * delete _write_call; * } * * void YourElement::function() { * // call _read_call, print result * if (_read_call) * click_chatter("%s", _read_call->call_read()); * * // call _write_call with error handler * if (_write_call) * _write_call->call_write(ErrorHandler::default_handler()); * } * @endcode */class HandlerCall { public: /** @name Immediate Handler Calls */ //@{ static String call_read(Element *e, const String &hname, ErrorHandler *errh = 0); static String call_read(const String &hdesc, const Element *context, ErrorHandler *errh = 0); static int call_write(Element *e, const String &hname, ErrorHandler *errh = 0); static int call_write(Element *e, const String &hname, const String &value, ErrorHandler *errh = 0); static int call_write(const String &hdesc, const Element *context, ErrorHandler *errh = 0); static int call_write(const String &hdesc, const String &value, const Element *context, ErrorHandler *errh = 0); //@} /** @brief Construct an empty HandlerCall. * * Any attempt to read, write, or initialize the HandlerCall will * fail. */ HandlerCall() : _e(0), _h(Handler::blank_handler()) { } /** @brief Construct a HandlerCall described by @a hdesc. * @param hdesc handler description <tt>"[ename.]hname[ value]"</tt> * * Although the resulting HandlerCall isn't empty, it must be initialized * before it can be used. It returns false for initialized(). The * handler description is not checked for syntax errors, though; * initialize() does that. */ HandlerCall(const String &hdesc) : _e(reinterpret_cast<Element *>(4)), _h(Handler::blank_handler()), _value(hdesc) { } enum Flags { OP_READ = Handler::OP_READ, OP_WRITE = Handler::OP_WRITE, PREINITIALIZE = 4 }; /** @brief Initialize the HandlerCall. * @param flags zero or more of OP_READ, OP_WRITE, PREINITIALIZE * @param context optional element context * @param errh optional error handler * @return 0 on success, negative on failure * * Initializes the HandlerCall object. The handler description supplied * to the constructor is parsed and checked for syntax errors. Any * element reference is looked up relative to @a context, if any. (For * example, if @a hdesc was "x.config" and @a context's name is * "aaa/bbb/ccc", this will search for elements named aaa/bbb/x, aaa/x, * and finally x. If @a context is null, then the description must refer * to a global handler.) If OP_READ is set in @a flags, then there * must be a read handler named appropriately; if OP_WRITE is set, * then there must be a write handler. * * Initialization fails if the handler description was bogus (for * example, an empty string, or something like "*#!$&!(#&$."), if the * named handler does not exist, if a read handler description has * parameters but the read handler doesn't actually take parameters, and * so forth. If @a errh is nonnull, errors are reported there. The * HandlerCall becomes empty on failure: empty() will return true, and * (bool) *this will return false. Future call_read() and call_write() * attempts will correctly fail. * * If the PREINITIALIZE flag is set, the initialize function will check * whether the router's handlers are ready (Router::handlers_ready()). * If handlers are not ready, then initialize() will check for syntax * errors, but not actually look up the handler (since we don't know yet * whether or not the handler exists). Absent a syntax error, * initialize() will return 0 for success even though the HandlerCall * remains uninitialized. */ int initialize(int flags, const Element *context, ErrorHandler *errh = 0); /** @brief Initialize the HandlerCall for reading. * @param context optional element context * @param errh optional error handler * * Equivalent to @link initialize(int, Element*, ErrorHandler*) * initialize@endlink(OP_READ, @a context, @a errh). */ inline int initialize_read(const Element *context, ErrorHandler *errh = 0); /** @brief Initialize the HandlerCall for writing. * @param context optional element context * @param errh optional error handler * * Equivalent to @link initialize(int, Element*, ErrorHandler*) * initialize@endlink(OP_WRITE, @a context, @a errh). */ inline int initialize_write(const Element *context, ErrorHandler *errh = 0); typedef bool (HandlerCall::*unspecified_bool_type)() const; /** @brief Test if HandlerCall is empty. * @return True if HandlerCall is not empty, false otherwise. * * Valid HandlerCall objects have been successfully initialized. */ operator unspecified_bool_type() const { return _h != Handler::blank_handler() || _e ? &HandlerCall::empty : 0; } /** @brief Test if HandlerCall is empty. * @return True if HandlerCall is empty, false otherwise. */ bool empty() const { return _h == Handler::blank_handler() && !_e; } /** @brief Test if HandlerCall is initialized. * @return True if HandlerCall is initialized, false otherwise. */ bool initialized() const { return _h != Handler::blank_handler(); } /** @brief Call a read handler. * @param errh optional error handler * @return Read handler result. * * Fails and returns the empty string if this HandlerCall is invalid or * not a read handler. If @a errh is nonnull, then any errors are * reported there, whether from HandlerCall or the handler itself. */ inline String call_read(ErrorHandler *errh = 0) const; /** @brief Call a write handler. * @param errh optional error handler
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -