?? elementmap.cc
字號:
// -*- c-basic-offset: 4 -*-/* * elementmap.{cc,hh} -- an element map class * Eddie Kohler * * Copyright (c) 1999-2000 Massachusetts Institute of Technology * Copyright (c) 2000 Mazu Networks, Inc. * Copyright (c) 2001 International Computer Science Institute * Copyright (c) 2008-2009 Meraki, Inc. * * 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 "elementmap.hh"#include "toolutils.hh"#include <click/confparse.hh>int32_t ElementMap::version_counter = 0;static ElementMap main_element_map;ElementMap *ElementMap::the_element_map = &main_element_map;static Vector<ElementMap *> element_map_stack;ElementMap::ElementMap() : _name_map(0), _use_count(0), _driver_mask(Driver::ALLMASK), _provided_driver_mask(0){ _e.push_back(Traits()); _def.push_back(Globals()); incr_version();}ElementMap::ElementMap(const String& str, ErrorHandler* errh) : _name_map(0), _use_count(0), _driver_mask(Driver::ALLMASK), _provided_driver_mask(0){ _e.push_back(Traits()); _def.push_back(Globals()); parse(str, errh); incr_version();}ElementMap::~ElementMap(){ assert(_use_count == 0);}voidElementMap::push_default(ElementMap *em){ em->use(); element_map_stack.push_back(the_element_map); the_element_map = em;}voidElementMap::pop_default(){ ElementMap *old = the_element_map; if (element_map_stack.size()) { the_element_map = element_map_stack.back(); element_map_stack.pop_back(); } else the_element_map = &main_element_map; old->unuse();}intElementMap::driver_elt_index(int i) const{ while (i > 0 && (_e[i].driver_mask & _driver_mask) == 0) i = _e[i].name_next; return i;}StringElementMap::documentation_url(const ElementTraits &t) const{ String name = t.documentation_name; if (name) return percent_substitute(_def[t.def_index].dochref, 's', name.c_str(), 0); else return "";}intElementMap::add(const Traits &e){ int i = _e.size(); _e.push_back(e); Traits &my_e = _e.back(); if (my_e.requirements) my_e.calculate_driver_mask(); if (e.name) { ElementClassT *c = ElementClassT::base_type(e.name); my_e.name_next = _name_map[c->name()]; _name_map.set(c->name(), i); } incr_version(); return i;}voidElementMap::remove_at(int i){ // XXX repeated removes can fill up ElementMap with crap if (i <= 0 || i >= _e.size()) return; Traits &e = _e[i]; int p = -1; for (int t = _name_map.get(e.name); t > 0; p = t, t = _e[t].name_next) /* nada */; if (p >= 0) _e[p].name_next = e.name_next; else if (e.name) _name_map.set(e.name, e.name_next); e.name = e.cxx = String(); incr_version();}static const char *parse_attribute_value(String *result, const char *s, const char *ends, const HashTable<String, String> &entities, ErrorHandler *errh){ while (s < ends && isspace((unsigned char) *s)) s++; if (s >= ends || (*s != '\'' && *s != '\"')) { errh->error("XML parse error: missing attribute value"); return s; } char quote = *s; const char *first = s + 1; StringAccum sa; for (s++; s < ends && *s != quote; s++) if (*s == '&') { // dump on normal text sa.append(first, s - first); if (s + 3 < ends && s[1] == '#' && s[2] == 'x') { // hex character reference int c = 0; for (s += 3; isxdigit((unsigned char) *s); s++) if (isdigit((unsigned char) *s)) c = (c * 16) + *s - '0'; else c = (c * 16) + tolower((unsigned char) *s) - 'a' + 10; sa << (char)c; } else if (s + 2 < ends && s[1] == '#') { // decimal character reference int c = 0; for (s += 2; isdigit((unsigned char) *s); s++) c = (c * 10) + *s - '0'; sa << (char)c; } else { // named entity const char *t; for (t = s + 1; t < ends && *t != quote && *t != ';'; t++) /* nada */; if (t < ends && *t == ';') { String entity_name(s + 1, t - s - 1); sa << entities[entity_name]; s = t; } } // check entity ended correctly if (s >= ends || *s != ';') { errh->error("XML parse error: bad entity name"); return s; } first = s + 1; } sa.append(first, s - first); if (s >= ends) errh->error("XML parse error: unterminated attribute value"); else s++; *result = sa.take_string(); return s;}static const char *parse_xml_attrs(HashTable<String, String> &attrs, const char *s, const char *ends, bool *closed, const HashTable<String, String> &entities, ErrorHandler *errh){ while (s < ends) { while (s < ends && isspace((unsigned char) *s)) s++; if (s >= ends) return s; else if (*s == '/') { *closed = true; return s; } else if (*s == '>') return s; // get attribute name const char *attrstart = s; while (s < ends && !isspace((unsigned char) *s) && *s != '=') s++; if (s == attrstart) { errh->error("XML parse error: missing attribute name"); return s; } String attrname(attrstart, s - attrstart); // skip whitespace and equals sign while (s < ends && isspace((unsigned char) *s)) s++; if (s >= ends || *s != '=') { errh->error("XML parse error: missing %<=%>"); return s; } s++; // get attribute value String attrvalue; s = parse_attribute_value(&attrvalue, s, ends, entities, errh); attrs.set(attrname, attrvalue); } return s;}voidElementMap::parse_xml(const String &str, const String &package_name, ErrorHandler *errh){ if (!errh) errh = ErrorHandler::silent_handler(); // prepare entities HashTable<String, String> entities; entities.set("lt", "<"); entities.set("amp", "&"); entities.set("gt", ">"); entities.set("quot", "\""); entities.set("apos", "'"); const char *s = str.data(); const char *ends = s + str.length(); bool in_elementmap = false; while (s < ends) { // skip to '<' while (s < ends && *s != '<') s++; for (s++; s < ends && isspace((unsigned char) *s); s++) /* nada */; bool closed = false; if (s < ends && *s == '/') { closed = true; for (s++; s < ends && isspace((unsigned char) *s); s++) /* nada */; } // which tag if (s + 10 < ends && memcmp(s, "elementmap", 10) == 0 && (isspace((unsigned char) s[10]) || s[10] == '>' || s[10] == '/')) { // parse elementmap tag if (!closed) { if (in_elementmap) errh->error("XML elementmap parse error: nested <elementmap> tags"); HashTable<String, String> attrs; s = parse_xml_attrs(attrs, s + 10, ends, &closed, entities, errh); Globals g; g.package = (attrs["package"] ? attrs["package"] : package_name); g.srcdir = attrs["sourcedir"]; if (attrs["src"].substring(0, 7) == "file://") g.srcdir = attrs["src"].substring(7); g.dochref = attrs["dochref"]; if (!g.dochref) g.dochref = attrs["webdoc"]; if (attrs["provides"]) _e[0].provisions += " " + attrs["provides"]; g.driver_mask = Driver::ALLMASK; if (attrs["drivers"]) g.driver_mask = Driver::driver_mask(attrs["drivers"]); if (!_provided_driver_mask) _provided_driver_mask = g.driver_mask; _def.push_back(g); in_elementmap = true; } if (closed) in_elementmap = false; } else if (s + 5 < ends && memcmp(s, "entry", 5) == 0 && (isspace((unsigned char) s[5]) || s[5] == '>' || s[5] == '/') && !closed && in_elementmap) { // parse entry tag HashTable<String, String> attrs; s = parse_xml_attrs(attrs, s + 5, ends, &closed, entities, errh); Traits elt; for (HashTable<String, String>::iterator i = attrs.begin(); i.live(); i++) if (String *sp = elt.component(i.key())) *sp = i.value(); if (elt.provisions || elt.name) { elt.def_index = _def.size() - 1; (void) add(elt); } } else if (s + 7 < ends && memcmp(s, "!ENTITY", 7) == 0 && (isspace((unsigned char) s[7]) || s[7] == '>' || s[7] == '/')) { // parse entity declaration for (s += 7; s < ends && isspace((unsigned char) *s); s++) /* nada */; if (s >= ends || *s == '%') // skip DTD entities break; const char *name_start = s; while (s < ends && !isspace((unsigned char) *s)) s++; String name(name_start, s - name_start), value; s = parse_attribute_value(&value, s, ends, entities, errh); entities.set(name, value); } else if (s + 8 < ends && memcmp(s, "![CDATA[", 8) == 0) { // skip CDATA section for (s += 8; s < ends; s++) if (*s == ']' && s + 3 <= ends && memcmp(s, "]]>", 3) == 0) break; } else if (s + 3 < ends && memcmp(s, "!--", 3) == 0) { // skip comment for (s += 3; s < ends; s++) if (*s == '-' && s + 3 <= ends && memcmp(s, "-->", 3) == 0) break; } // skip to '>' while (s < ends && *s != '>') s++; }}voidElementMap::parse(const String &str, const String &package_name, ErrorHandler *errh){ if (str.length() && str[0] == '<') { parse_xml(str, package_name, errh); return;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -