314 lines
8.4 KiB
C++
314 lines
8.4 KiB
C++
// -*- c-basic-offset: 4 -*-
|
|
#ifndef CLICK_ELEMENTT_HH
|
|
#define CLICK_ELEMENTT_HH
|
|
#include "eclasst.hh"
|
|
#include "landmarkt.hh"
|
|
|
|
class ElementT { public:
|
|
|
|
int flags;
|
|
|
|
ElementT();
|
|
ElementT(const String &name, ElementClassT *type, const String &config, const LandmarkT &landmark = LandmarkT::empty_landmark());
|
|
~ElementT();
|
|
|
|
RouterT *router() const { return _owner; }
|
|
int eindex() const { return _eindex; }
|
|
|
|
bool live() const { return _type; }
|
|
bool dead() const { return !_type; }
|
|
void kill();
|
|
|
|
const String &name() const { return _name; }
|
|
const char *name_c_str() const { return _name.c_str(); }
|
|
bool name_unassigned() const { return _name && _name[0] == ';'; }
|
|
bool was_anonymous() const { return _was_anonymous; }
|
|
|
|
ElementClassT *type() const { return _type; }
|
|
ElementClassT *resolve(const VariableEnvironment &env,
|
|
VariableEnvironment *new_env,
|
|
ErrorHandler *errh = 0) const;
|
|
ElementClassT *resolved_type(const VariableEnvironment &env, ErrorHandler *errh = 0) const;
|
|
|
|
String type_name() const { return _type->name(); }
|
|
String printable_type_name() const { return _type->printable_name(); }
|
|
const char *type_name_c_str() const { return _type->printable_name_c_str(); }
|
|
|
|
void set_type(ElementClassT *);
|
|
inline RouterT *resolved_router(const VariableEnvironment &env, ErrorHandler *errh = 0) const;
|
|
|
|
inline const String &flow_code(ElementMap *emap) const;
|
|
inline const String &flow_code() const;
|
|
|
|
const String &config() const { return _configuration; }
|
|
const String &configuration() const { return _configuration; }
|
|
inline void set_configuration(const String &s);
|
|
|
|
const LandmarkT &landmarkt() const { return _landmark; }
|
|
String landmark() const { return _landmark.str(); }
|
|
String decorated_landmark() const { return _landmark.decorated_str(); }
|
|
void set_landmark(const LandmarkT &lm) { _landmark = lm; }
|
|
|
|
inline bool tunnel() const;
|
|
inline bool tunnel_connected() const;
|
|
ElementT *tunnel_input() const { return _tunnel_input; }
|
|
ElementT *tunnel_output() const { return _tunnel_output; }
|
|
|
|
int nports(bool isoutput) const { return isoutput ? _noutputs : _ninputs; }
|
|
int ninputs() const { return _ninputs; }
|
|
int noutputs() const { return _noutputs; }
|
|
|
|
inline String declaration() const;
|
|
inline String reverse_declaration() const;
|
|
|
|
void *user_data() const { return _user_data; }
|
|
void set_user_data(void *v) { _user_data = v; }
|
|
void set_user_data(intptr_t v) { _user_data = (void *)v; }
|
|
|
|
static bool name_ok(const String &, bool allow_anon_names = false);
|
|
static void redeclaration_error(ErrorHandler *, const char *type, String name, const String &landmark, const String &old_landmark);
|
|
|
|
private:
|
|
|
|
int _eindex;
|
|
String _name;
|
|
ElementClassT *_type;
|
|
mutable ElementClassT *_resolved_type;
|
|
enum { resolved_type_error = 1, resolved_type_fragile = 2 };
|
|
mutable short _resolved_type_status;
|
|
bool _was_anonymous;
|
|
String _configuration;
|
|
LandmarkT _landmark;
|
|
int _ninputs;
|
|
int _noutputs;
|
|
ElementT *_tunnel_input;
|
|
ElementT *_tunnel_output;
|
|
RouterT *_owner;
|
|
void *_user_data;
|
|
|
|
ElementT(const ElementT &);
|
|
ElementT &operator=(const ElementT &);
|
|
|
|
inline void semiresolve_type() const {
|
|
if (!_resolved_type && _type && _type->primitive()) {
|
|
_resolved_type = _type;
|
|
_resolved_type->use();
|
|
}
|
|
}
|
|
inline void unresolve_type() {
|
|
if (_resolved_type) {
|
|
_resolved_type->unuse();
|
|
_resolved_type = 0;
|
|
}
|
|
}
|
|
inline void set_ninputs(int n) {
|
|
unresolve_type();
|
|
_ninputs = n;
|
|
}
|
|
inline void set_noutputs(int n) {
|
|
unresolve_type();
|
|
_noutputs = n;
|
|
}
|
|
|
|
friend class RouterT;
|
|
|
|
};
|
|
|
|
struct PortT {
|
|
|
|
ElementT *element;
|
|
int port;
|
|
|
|
PortT() : element(0), port(-1) { }
|
|
PortT(ElementT *e, int p) : element(e), port(p) { }
|
|
|
|
static const PortT null_port;
|
|
|
|
typedef bool (PortT::*unspecified_bool_type)() const;
|
|
|
|
operator unspecified_bool_type() const {
|
|
return element != 0 ? &PortT::live : 0;
|
|
}
|
|
|
|
bool live() const { return element != 0; }
|
|
bool dead() const { return element == 0; }
|
|
RouterT *router() const { return (element ? element->router() : 0); }
|
|
|
|
int eindex() const { return (element ? element->eindex() : -1); }
|
|
|
|
int index_in(const Vector<PortT> &, int start = 0) const;
|
|
int force_index_in(Vector<PortT> &, int start = 0) const;
|
|
|
|
String unparse(bool isoutput, bool with_class = false) const;
|
|
String unparse_input(bool with_class = false) const {
|
|
return unparse(false, with_class);
|
|
}
|
|
String unparse_output(bool with_class = false) const {
|
|
return unparse(true, with_class);
|
|
}
|
|
|
|
static void sort(Vector<PortT> &);
|
|
|
|
};
|
|
|
|
class ConnectionT { public:
|
|
|
|
inline ConnectionT();
|
|
ConnectionT(const PortT &from, const PortT &to,
|
|
const LandmarkT &landmark = LandmarkT::empty_landmark());
|
|
|
|
typedef PortT::unspecified_bool_type unspecified_bool_type;
|
|
inline operator unspecified_bool_type() const;
|
|
|
|
enum { end_to = 0, end_from = 1 };
|
|
|
|
bool live() const { return _end[end_from].live(); }
|
|
bool dead() const { return _end[end_from].dead(); }
|
|
|
|
RouterT *router() const { return _end[end_to].router(); }
|
|
|
|
const PortT &end(bool isoutput) const {
|
|
return _end[isoutput];
|
|
}
|
|
ElementT *element(bool isoutput) const {
|
|
return _end[isoutput].element;
|
|
}
|
|
int eindex(bool isoutput) const {
|
|
return _end[isoutput].eindex();
|
|
}
|
|
int port(bool isoutput) const {
|
|
return _end[isoutput].port;
|
|
}
|
|
|
|
const PortT &from() const { return end(end_from); }
|
|
const PortT &to() const { return end(end_to); }
|
|
ElementT *from_element() const { return element(end_from); }
|
|
int from_eindex() const { return eindex(end_from); }
|
|
int from_port() const { return port(end_from); }
|
|
ElementT *to_element() const { return element(end_to); }
|
|
int to_eindex() const { return eindex(end_to); }
|
|
int to_port() const { return port(end_to); }
|
|
String landmark() const { return _landmark.str(); }
|
|
String decorated_landmark() const { return _landmark.decorated_str(); }
|
|
const LandmarkT &landmarkt() const { return _landmark; }
|
|
|
|
String unparse(bool with_class = false) const;
|
|
String unparse_end(bool isoutput, bool with_class = false) const {
|
|
return end(isoutput).unparse(isoutput, with_class);
|
|
}
|
|
|
|
private:
|
|
|
|
PortT _end[2];
|
|
LandmarkT _landmark;
|
|
|
|
friend class RouterT;
|
|
|
|
};
|
|
|
|
|
|
inline RouterT *
|
|
ElementT::resolved_router(const VariableEnvironment &env, ErrorHandler *errh) const
|
|
{
|
|
if (ElementClassT *t = resolved_type(env, errh))
|
|
return t->cast_router();
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
inline void
|
|
ElementT::set_configuration(const String &configuration)
|
|
{
|
|
_configuration = configuration;
|
|
unresolve_type();
|
|
}
|
|
|
|
inline String
|
|
ElementT::declaration() const
|
|
{
|
|
assert(_type);
|
|
return _name + " :: " + _type->printable_name();
|
|
}
|
|
|
|
inline String
|
|
ElementT::reverse_declaration() const
|
|
{
|
|
assert(_type);
|
|
return _type->printable_name() + " " + _name;
|
|
}
|
|
|
|
inline bool
|
|
ElementT::tunnel() const
|
|
{
|
|
return _type == ElementClassT::tunnel_type();
|
|
}
|
|
|
|
inline bool
|
|
ElementT::tunnel_connected() const
|
|
{
|
|
return _tunnel_input || _tunnel_output;
|
|
}
|
|
|
|
inline const String &
|
|
ElementT::flow_code(ElementMap *emap) const
|
|
{
|
|
semiresolve_type();
|
|
return _resolved_type->traits(emap).flow_code;
|
|
}
|
|
|
|
inline const String &
|
|
ElementT::flow_code() const
|
|
{
|
|
semiresolve_type();
|
|
return _resolved_type->traits(ElementMap::default_map()).flow_code;
|
|
}
|
|
|
|
inline bool
|
|
operator==(const PortT &h1, const PortT &h2)
|
|
{
|
|
return h1.element == h2.element && h1.port == h2.port;
|
|
}
|
|
|
|
inline bool
|
|
operator!=(const PortT &h1, const PortT &h2)
|
|
{
|
|
return h1.element != h2.element || h1.port != h2.port;
|
|
}
|
|
|
|
inline bool
|
|
operator<(const PortT &h1, const PortT &h2)
|
|
{
|
|
return h1.eindex() < h2.eindex() || (h1.element == h2.element && h1.port < h2.port);
|
|
}
|
|
|
|
inline bool
|
|
operator>(const PortT &h1, const PortT &h2)
|
|
{
|
|
return h1.eindex() > h2.eindex() || (h1.element == h2.element && h1.port > h2.port);
|
|
}
|
|
|
|
inline bool
|
|
operator<=(const PortT &h1, const PortT &h2)
|
|
{
|
|
return h1.eindex() < h2.eindex() || (h1.element == h2.element && h1.port <= h2.port);
|
|
}
|
|
|
|
inline bool
|
|
operator>=(const PortT &h1, const PortT &h2)
|
|
{
|
|
return h1.eindex() > h2.eindex() || (h1.element == h2.element && h1.port >= h2.port);
|
|
}
|
|
|
|
inline
|
|
ConnectionT::ConnectionT()
|
|
{
|
|
}
|
|
|
|
inline
|
|
ConnectionT::operator unspecified_bool_type() const
|
|
{
|
|
return (unspecified_bool_type) _end[end_from];
|
|
}
|
|
|
|
#endif
|