// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*- // vim:set sts=4 ts=8: // Copyright (c) 2001-2009 XORP, Inc. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License, Version // 2.1, June 1999 as published by the Free Software Foundation. // Redistribution and/or modification of this program under the terms of // any other version of the GNU Lesser General Public License is not // permitted. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details, // see the GNU Lesser General Public License, Version 2.1, a copy of // which can be found in the XORP LICENSE.lgpl file. // // XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA; // http://xorp.net // $XORP: xorp/libxipc/xrl_atom.hh,v 1.24 2009/01/05 18:30:56 jtc Exp $ #ifndef __LIBXIPC_XRL_ATOM_HH__ #define __LIBXIPC_XRL_ATOM_HH__ #include "libxorp/xorp.h" #include "libxorp/c_format.hh" #include "libxorp/exceptions.hh" #include "libxorp/ipv4.hh" #include "libxorp/ipv4net.hh" #include "libxorp/ipv6.hh" #include "libxorp/ipv6net.hh" #include "libxorp/ipvx.hh" #include "libxorp/ipvxnet.hh" #include "libxorp/mac.hh" #include <string> #include <vector> #include "xrl_atom_list.hh" enum XrlAtomType { xrlatom_no_type = 0, xrlatom_int32, xrlatom_uint32, xrlatom_ipv4, xrlatom_ipv4net, xrlatom_ipv6, xrlatom_ipv6net, xrlatom_mac, xrlatom_text, xrlatom_list, xrlatom_boolean, xrlatom_binary, xrlatom_int64, xrlatom_uint64, // ... Your type's unique enumerated name here ... // Changing order above will break binary compatibility // ...Don't forget to update xrlatom_start and xrlatom_end below... // Bounds for enumerations xrlatom_start = xrlatom_int32, // First valid enumerated value xrlatom_end = xrlatom_uint64 // Last valid enumerated value }; inline XrlAtomType& operator++(XrlAtomType& t) { return t = (xrlatom_end == t) ? xrlatom_no_type : XrlAtomType(t + 1); } /** * @return name of atom corresponding to type. */ const char* xrlatom_type_name(const XrlAtomType&); class XrlAtom { public: // Exceptions struct NoData : public XorpException { NoData(const char* file, int line, const string& name) : XorpException("XrlAtom::NoData", file, line), _name(name) {} const string why() const { return c_format("Atom name %s has no data", _name.c_str()); } private: string _name; }; struct WrongType : public XorpException { WrongType(const char* file, int line, const XrlAtomType& actual, const XrlAtomType& expected) : XorpException("XrlAtom::WrongType", file, line), _actual(actual), _expected(expected) {} const string why() const { return c_format("Atom type %s (%d) expected %s (%d)", xrlatom_type_name(_actual), _actual, xrlatom_type_name(_expected), _expected); } private: XrlAtomType _actual; XrlAtomType _expected; }; struct BadName : public XorpException { BadName(const char* file, int line, const char* name) : XorpException("XrlAtom::BadName", file, line), _name(name) {} const string why() const { return c_format("\"%s\" is not a valid name", _name.c_str()); } private: string _name; }; XrlAtom() : _type(xrlatom_no_type), _have_data(false), _own(true) {} ~XrlAtom(); // type but no data constructors XrlAtom(XrlAtomType t) : _type(t), _have_data(false), _own(true) {} XrlAtom(const string& name, XrlAtomType t) throw (BadName) : _type(t), _have_data(false), _own(true) { set_name(name); } XrlAtom(const char* name, XrlAtomType t) throw (BadName) : _type(t), _have_data(false), _own(true) { set_name(name); } XrlAtom(const string& name, XrlAtomType t, const string& serialized_data) throw (InvalidString); XrlAtom(const char* name, XrlAtomType t, const string& serialized_data) throw (InvalidString); /** * Construct an XrlAtom from it's serialized character representation. * * Be careful not confuse this with the unnamed string atom constructor * XrlAtom(const string&). * */ explicit XrlAtom(const char*) throw (InvalidString, BadName); // int32 constructors explicit XrlAtom(const int32_t& value) : _type(xrlatom_int32), _have_data(true), _own(true), _i32val(value) {} XrlAtom(const char* name, int32_t value) throw (BadName) : _type(xrlatom_int32), _have_data(true), _own(true) ,_i32val(value) { set_name(name); } // bool constructors explicit XrlAtom(const bool& value) : _type(xrlatom_boolean), _have_data(true), _own(true), _boolean(value) {} XrlAtom(const char* name, bool value) throw (BadName) : _type(xrlatom_boolean), _have_data(true), _own(true), _boolean(value) { set_name(name); } // uint32 constructors explicit XrlAtom(const uint32_t& value) : _type(xrlatom_uint32), _have_data(true), _own(true), _u32val(value) {} XrlAtom(const char* name, uint32_t value) throw (BadName) : _type(xrlatom_uint32), _have_data(true), _own(true), _u32val(value) { set_name(name); } // ipv4 constructors explicit XrlAtom(const IPv4& addr) : _type(xrlatom_ipv4), _have_data(true), _own(true), _ipv4(new IPv4(addr)) {} XrlAtom(const char* name, const IPv4& addr) throw (BadName) : _type(xrlatom_ipv4), _have_data(true), _own(true), _ipv4(new IPv4(addr)) { set_name(name); } // ipv4net constructors explicit XrlAtom(const IPv4Net& subnet) : _type(xrlatom_ipv4net), _have_data(true), _own(true), _ipv4net(new IPv4Net(subnet)) {} XrlAtom(const char* name, const IPv4Net& subnet) throw (BadName) : _type(xrlatom_ipv4net), _have_data(true), _own(true), _ipv4net(new IPv4Net(subnet)) { set_name(name); } // ipv6 constructors explicit XrlAtom(const IPv6& addr) : _type(xrlatom_ipv6), _have_data(true), _own(true), _ipv6(new IPv6(addr)) {} XrlAtom(const char* name, const IPv6& addr) throw (BadName) : _type(xrlatom_ipv6), _have_data(true), _own(true), _ipv6(new IPv6(addr)) { set_name(name); } // ipv6 net constructors explicit XrlAtom(const IPv6Net& subnet) : _type(xrlatom_ipv6net), _have_data(true), _own(true), _ipv6net(new IPv6Net(subnet)) {} XrlAtom(const char* name, const IPv6Net& subnet) throw (BadName) : _type(xrlatom_ipv6net), _have_data(true), _own(true), _ipv6net(new IPv6Net(subnet)) { set_name(name); } // IPvX constructors - there is no underlying IPvX type // data is cast to IPv4 or IPv6. XrlAtom(const char* name, const IPvX& ipvx) throw (BadName) : _have_data(true), _own(true) { set_name(name); if (ipvx.is_ipv4()) { _type = xrlatom_ipv4; _ipv4 = new IPv4(ipvx.get_ipv4()); } else if (ipvx.is_ipv6()) { _type = xrlatom_ipv6; _ipv6 = new IPv6(ipvx.get_ipv6()); } else { abort(); } } // IPvXNet constructors - there is no underlying IPvXNet type // data is cast to IPv4Net or IPv6Net. XrlAtom(const char* name, const IPvXNet& ipvxnet) throw (BadName) : _have_data(true), _own(true) { set_name(name); if (ipvxnet.is_ipv4()) { _type = xrlatom_ipv4net; _ipv4net = new IPv4Net(ipvxnet.get_ipv4net()); } else if (ipvxnet.is_ipv6()) { _type = xrlatom_ipv6net; _ipv6net = new IPv6Net(ipvxnet.get_ipv6net()); } else { abort(); } } // mac constructors explicit XrlAtom(const Mac& mac) : _type(xrlatom_mac), _have_data(true), _own(true), _mac(new Mac(mac)) {} XrlAtom(const char* name, const Mac& mac) throw (BadName) : _type(xrlatom_mac), _have_data(true), _own(true), _mac(new Mac(mac)) { set_name(name); } // text constructors explicit XrlAtom(const string& txt) : _type(xrlatom_text), _have_data(true), _own(true), _text(new string(txt)) {} XrlAtom(const char* name, const string& txt) throw (BadName) : _type(xrlatom_text), _have_data(true), _own(true), _text(new string(txt)) { set_name(name); } // list constructors explicit XrlAtom(const XrlAtomList& l) : _type(xrlatom_list), _have_data(true), _own(true), _list(new XrlAtomList(l)) {} XrlAtom(const char* name, const XrlAtomList& l) throw (BadName) : _type(xrlatom_list), _have_data(true), _own(true), _list(new XrlAtomList(l)) { set_name(name); } // binary XrlAtom(const char* name, const vector<uint8_t>& data) : _type(xrlatom_binary), _have_data(true), _own(true), _binary(new vector<uint8_t>(data)) { set_name(name); } XrlAtom(const char* name, const uint8_t* data, size_t data_bytes) : _type(xrlatom_binary), _have_data(true), _own(true), _binary(new vector<uint8_t>(data, data + data_bytes)) { set_name(name); } XrlAtom(const vector<uint8_t>& data) : _type(xrlatom_binary), _have_data(true), _own(true), _binary(new vector<uint8_t>(data)) {} XrlAtom(const uint8_t* data, size_t data_bytes) : _type(xrlatom_binary), _have_data(true), _own(true), _binary(new vector<uint8_t>(data, data + data_bytes)) {} // int64 constructors explicit XrlAtom(const int64_t& value) : _type(xrlatom_int64), _have_data(true), _own(true), _i64val(value) {} XrlAtom(const char* name, int64_t value) throw (BadName) : _type(xrlatom_int64), _have_data(true), _own(true), _i64val(value) { set_name(name); } // uint64 constructors explicit XrlAtom(const uint64_t& value) : _type(xrlatom_uint64), _have_data(true), _own(true), _u64val(value) {} XrlAtom(const char* name, uint64_t value) throw (BadName) : _type(xrlatom_uint64), _have_data(true), _own(true), _u64val(value) { set_name(name); } // ... Your type's constructors here ... // Copy operations XrlAtom(const XrlAtom& x) : _type(xrlatom_no_type), _have_data(false), _own(true) { copy(x); } XrlAtom& operator=(const XrlAtom& x) { discard_dynamic(); copy(x); return *this; } void copy(const XrlAtom& x); // Accessor operations const string& name() const { return _atom_name; } void set_name(const string& n) throw (BadName) { set_name (n.c_str()); } string str() const; const string type_name() const; const string value() const; const bool& has_data() const { return _have_data; } const XrlAtomType& type() const { return _type; } // The following accessors may throw accessor exceptions... const bool& boolean() const throw (NoData, WrongType); const int32_t& int32() const throw (NoData, WrongType); const uint32_t& uint32() const throw (NoData, WrongType); const IPv4& ipv4() const throw (NoData, WrongType); const IPv4Net& ipv4net() const throw (NoData, WrongType); const IPv6& ipv6() const throw (NoData, WrongType); const IPv6Net& ipv6net() const throw (NoData, WrongType); const IPvX ipvx() const throw (NoData, WrongType); const IPvXNet ipvxnet() const throw (NoData, WrongType); const Mac& mac() const throw (NoData, WrongType); const string& text() const throw (NoData, WrongType); const XrlAtomList& list() const throw (NoData, WrongType); const vector<uint8_t>& binary() const throw (NoData, WrongType); const int64_t& int64() const throw (NoData, WrongType); const uint64_t& uint64() const throw (NoData, WrongType); // ... Your type's accessor method here ... // set methods #define SET(type, var, p) \ void set(const type& arg) \ { \ abandon_data(); \ \ type& a = const_cast<type&>(arg); \ var = p a; \ } SET(int32_t, _i32val, ) SET(uint32_t, _u32val, ) SET(int64_t, _i64val, ) SET(uint64_t, _u64val, ) SET(bool, _boolean, ) SET(IPv4, _ipv4, &) SET(IPv4Net, _ipv4net, &) SET(IPv6, _ipv6, &) SET(IPv6Net, _ipv6net, &) SET(Mac, _mac, &) SET(string, _text, &) SET(XrlAtomList, _list, &) SET(vector<uint8_t>, _binary, &); #undef SET // Equality tests bool operator==(const XrlAtom& x) const; // Binary packing and unpacking operations bool packed_bytes_fixed() const; size_t packed_bytes() const; size_t pack(uint8_t* buffer, size_t bytes_available) const; size_t unpack(const uint8_t* buffer, size_t buffer_bytes); static bool valid_type(const string& s); static bool valid_name(const string& s); static XrlAtomType lookup_type(const string& s) { return resolve_type_c_str(s.c_str()); } static size_t peek_text(const char*& t, uint32_t& tl, const uint8_t* buf, size_t len); private: void discard_dynamic(); void abandon_data(); void type_and_data_okay(const XrlAtomType& t) const throw (NoData, WrongType); void set_name(const char *n) throw (BadName); static XrlAtomType resolve_type_c_str(const char*); ssize_t data_from_c_str(const char* c_str); size_t pack_name(uint8_t* buffer) const; size_t pack_boolean(uint8_t* buffer) const; size_t pack_uint32(uint8_t* buffer) const; size_t pack_ipv4(uint8_t* buffer) const; size_t pack_ipv4net(uint8_t* buffer) const; size_t pack_ipv6(uint8_t* buffer) const; size_t pack_ipv6net(uint8_t* buffer) const; size_t pack_mac(uint8_t* buffer) const; size_t pack_text(uint8_t* buffer) const; size_t pack_list(uint8_t* buffer, size_t buffer_bytes) const; size_t pack_binary(uint8_t* buffer) const; size_t pack_uint64(uint8_t* buffer) const; size_t unpack_name(const uint8_t* buffer, size_t buffer_bytes) throw (BadName); size_t unpack_boolean(const uint8_t* buffer); size_t unpack_uint32(const uint8_t* buffer); size_t unpack_ipv4(const uint8_t* buffer); size_t unpack_ipv4net(const uint8_t* buffer); size_t unpack_ipv6(const uint8_t* buffer); size_t unpack_ipv6net(const uint8_t* buffer); size_t unpack_mac(const uint8_t* buffer, size_t buffer_bytes); size_t unpack_text(const uint8_t* buffer, size_t buffer_bytes); size_t unpack_list(const uint8_t* buffer, size_t buffer_bytes); size_t unpack_binary(const uint8_t* buffer, size_t buffer_bytes); size_t unpack_uint64(const uint8_t* buffer); private: XrlAtomType _type; bool _have_data; string _atom_name; bool _own; union { bool _boolean; int32_t _i32val; uint32_t _u32val; IPv4* _ipv4; IPv4Net* _ipv4net; IPv6* _ipv6; IPv6Net* _ipv6net; Mac* _mac; string* _text; XrlAtomList* _list; vector<uint8_t>* _binary; int64_t _i64val; uint64_t _u64val; // ... Your type here, if it's more than sizeof(uintptr_t) bytes, // use a pointer ... } ; }; // XrlAtomSpell is a placeholder class for Xrl mapping // It used to hold the name:type of an atom whose value we // wish to refer to. class XrlAtomSpell { public: XrlAtomSpell(const XrlAtom& xa, const string& spell) : _xa(xa), _spell(spell) {} XrlAtomSpell(const string& name, const XrlAtomType& type, const string& m) : _xa(XrlAtom(name, type)), _spell(m) {} const string& atom_name() const { return _xa.name(); } const XrlAtomType& atom_type() const { return _xa.type(); } const XrlAtom& atom() const { return _xa; } const string& spell() const { return _spell; } protected: const XrlAtom _xa; const string _spell; }; #endif // __LIBXIPC_XRL_ATOM_HH__