// -*- c-basic-offset: 2; related-file-name: "../../include/click/standard/alignmentinfo.hh" -*-
/*
* alignmentinfo.{cc,hh} -- element stores alignment information
* Eddie Kohler
*
* Copyright (c) 1999-2000 Massachusetts Institute of Technology
*
* 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/standard/alignmentinfo.hh>
#include <click/glue.hh>
#include <click/confparse.hh>
#include <click/router.hh>
#include <click/error.hh>
CLICK_DECLS
AlignmentInfo::AlignmentInfo()
{
}
AlignmentInfo::~AlignmentInfo()
{
}
int
AlignmentInfo::configure(Vector<String> &conf, ErrorHandler *errh)
{
// check for an earlier AlignmentInfo
if (void *a = router()->attachment("AlignmentInfo"))
return ((AlignmentInfo *)a)->configure(conf, errh);
router()->set_attachment("AlignmentInfo", this);
// this is the first AlignmentInfo; store all information here
for (int i = 0; i < conf.size(); i++) {
Vector<String> parts;
cp_spacevec(conf[i], parts);
if (parts.size() == 0)
errh->warning("empty configuration argument %d", i);
else if (Element *e = cp_element(parts[0], this, 0)) {
int number = e->eindex();
if (_elem_offset.size() <= number) {
_elem_offset.resize(number + 1, -1);
_elem_icount.resize(number + 1, -1);
}
// report an error if different AlignmentInfo is given
int old_offset = _elem_offset[number];
int old_icount = _elem_icount[number];
if (parts.size() % 2 != 1)
errh->error("expected 'ELEMENTNAME CHUNK OFFSET [CHUNK OFFSET...]'");
_elem_offset[number] = _chunks.size();
_elem_icount[number] = (parts.size() - 1) / 2;
for (int j = 1; j < parts.size() - 1; j += 2) {
int32_t c = -1, o = -1;
if (!cp_integer(parts[j], &c))
errh->error("expected CHUNK");
if (!cp_integer(parts[j+1], &o))
errh->error("expected OFFSET");
_chunks.push_back(c);
_offsets.push_back(o);
}
// check for conflicting information on duplicate AlignmentInfo
if (old_offset >= 0
&& (old_icount != _elem_icount[number]
|| memcmp(&_chunks[old_offset], &_chunks[_elem_offset[number]],
old_icount * sizeof(int)) != 0
|| memcmp(&_offsets[old_offset], &_offsets[_elem_offset[number]],
old_icount * sizeof(int)) != 0))
errh->error("conflicting AlignmentInfo for '%s'", parts[0].c_str());
}
}
return 0;
}
bool
AlignmentInfo::query1(Element *e, int port, int &chunk, int &offset) const
{
int idx = e->eindex();
if (idx < 0 || idx >= _elem_offset.size() || _elem_offset[idx] < 0
|| port >= _elem_icount[idx])
return false;
else {
chunk = _chunks[ _elem_offset[idx] + port ];
offset = _offsets[ _elem_offset[idx] + port ];
return true;
}
}
bool
AlignmentInfo::query(Element *e, int port, int &chunk, int &offset)
{
if (void *a = e->router()->attachment("AlignmentInfo"))
return ((AlignmentInfo *)a)->query1(e, port, chunk, offset);
else
return false;
}
CLICK_ENDDECLS
EXPORT_ELEMENT(AlignmentInfo)
ELEMENT_HEADER(<click/standard/alignmentinfo.hh>)
syntax highlighted by Code2HTML, v. 0.9.1