// -*- c-basic-offset: 4 -*-
/*
* etraits.{cc,hh} -- class records element traits
* Eddie Kohler
*
* Copyright (c) 1999-2000 Massachusetts Institute of Technology
* Copyright (c) 2000 Mazu Networks, Inc.
* Copyright (c) 2001 International Computer Science Institute
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, subject to the conditions
* listed in the Click LICENSE file. These conditions include: you must
* preserve this copyright notice, and you cannot mention the copyright
* holders in advertising related to the Software without their permission.
* The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
* notice is a summary of the Click LICENSE file; the license in that file is
* legally binding.
*/
#include <click/config.h>
#include <click/straccum.hh>
#include <click/bitvector.hh>
#include "routert.hh"
#include "lexert.hh"
#include "etraits.hh"
#include "toolutils.hh"
#include <click/confparse.hh>
static String::Initializer string_initializer;
ElementTraits ElementTraits::the_null_traits;
static const char * const driver_names[] = {
"userlevel", "linuxmodule", "bsdmodule", "ns"
};
const char *
Driver::name(int d)
{
static_assert(USERLEVEL == 0 && LINUXMODULE == 1 && BSDMODULE == 2 && NSMODULE == 3);
if (d >= 0 && d < COUNT)
return driver_names[d];
else
return "??";
}
const char *
Driver::requirement(int d)
{
if (d >= 0 && d < COUNT)
return driver_names[d];
else
return "";
}
int
Driver::driver(const String& name)
{
for (int d = 0; d < COUNT; d++)
if (name == driver_names[d])
return d;
return -1;
}
int
Driver::driver_mask(const String& name)
{
int d = driver(name);
if (d >= 0)
return 1 << d;
int m = 0;
const char* begin = name.begin(), *end_name = name.end(), *bar;
while ((bar = find(begin, end_name, '|')) < end_name) {
if ((d = driver(String(begin, bar).c_str())) >= 0)
m |= 1 << d;
begin = bar + 1;
}
return m;
}
static bool
requirement_contains(const String &req, const String &n)
{
assert(n.length());
int pos = 0;
while ((pos = req.find_left(n, pos)) >= 0) {
int rpos = pos + n.length();
// XXX should be more careful about '|' bars
if ((pos == 0 || isspace(req[pos - 1]) || req[pos - 1] == '|')
&& (rpos == req.length() || isspace(req[rpos]) || req[rpos] == '|'))
return true;
pos = rpos;
}
return false;
}
bool
ElementTraits::requires(const String &n) const
{
if (!requirements)
return false;
else
return requirement_contains(requirements, n);
}
bool
ElementTraits::provides(const String &n) const
{
if (n == name)
return true;
else if (!provisions)
return false;
else
return requirement_contains(provisions, n);
}
int
ElementTraits::flag_value(int flag) const
{
const unsigned char *data = reinterpret_cast<const unsigned char *>(flags.data());
int len = flags.length();
for (int i = 0; i < len; i++) {
if (data[i] == flag) {
if (i < len - 1 && isdigit(data[i+1])) {
int value = 0;
for (i++; i < len && isdigit(data[i]); i++)
value = 10*value + data[i] - '0';
return value;
} else
return 1;
} else
while (i < len && data[i] != ',')
i++;
}
return -1;
}
void
ElementTraits::calculate_driver_mask()
{
driver_mask = 0;
if (requirement_contains(requirements, "userlevel"))
driver_mask |= 1 << Driver::USERLEVEL;
if (requirement_contains(requirements, "linuxmodule"))
driver_mask |= 1 << Driver::LINUXMODULE;
if (requirement_contains(requirements, "bsdmodule"))
driver_mask |= 1 << Driver::BSDMODULE;
if (requirement_contains(requirements, "ns"))
driver_mask |= 1 << Driver::NSMODULE;
if (driver_mask == 0)
driver_mask = Driver::ALLMASK;
}
String *
ElementTraits::component(int what)
{
switch (what) {
case D_CLASS: return &name;
case D_CXX_CLASS: return &cxx;
case D_HEADER_FILE: return &header_file;
case D_SOURCE_FILE: return &source_file;
case D_PORT_COUNT: return &port_count_code;
case D_PROCESSING: return &processing_code;
case D_FLOW_CODE: return &flow_code;
case D_FLAGS: return &flags;
case D_METHODS: return &methods;
case D_REQUIREMENTS: return &requirements;
case D_PROVISIONS: return &provisions;
case D_LIBS: return &libs;
case D_DOC_NAME: return &documentation_name;
default: return 0;
}
}
static HashMap<String, int> components(ElementTraits::D_NONE);
static bool components_initialized = false;
int
ElementTraits::parse_component(const String &s)
{
if (!components_initialized) {
components.insert("name", D_CLASS);
components.insert("cxxclass", D_CXX_CLASS);
components.insert("headerfile", D_HEADER_FILE);
components.insert("sourcefile", D_SOURCE_FILE);
components.insert("portcount", D_PORT_COUNT);
components.insert("processing", D_PROCESSING);
components.insert("flowcode", D_FLOW_CODE);
components.insert("methods", D_METHODS);
components.insert("requires", D_REQUIREMENTS);
components.insert("provides", D_PROVISIONS);
components.insert("libs", D_LIBS);
components.insert("docname", D_DOC_NAME);
// for compatibility
components.insert("class", D_CLASS);
components.insert("cxx_class", D_CXX_CLASS);
components.insert("header_file", D_HEADER_FILE);
components.insert("source_file", D_SOURCE_FILE);
components.insert("requirements", D_REQUIREMENTS);
components.insert("provisions", D_PROVISIONS);
components.insert("doc_name", D_DOC_NAME);
}
return components[s];
}
ElementTraits
ElementTraits::make(int component, ...)
{
va_list val;
va_start(val, component);
ElementTraits t;
while (component != D_NONE) {
const char *x = va_arg(val, const char *);
if (String *c = t.component(component))
*c = x;
component = va_arg(val, int);
}
va_end(val);
return t;
}
// template instance
#include <click/vector.cc>
template class Vector<ElementTraits>;
syntax highlighted by Code2HTML, v. 0.9.1