xorp

xrl_atom.hh

00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
00002 // vim:set sts=4 ts=8:
00003 
00004 // Copyright (c) 2001-2011 XORP, Inc and Others
00005 //
00006 // This program is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU Lesser General Public License, Version
00008 // 2.1, June 1999 as published by the Free Software Foundation.
00009 // Redistribution and/or modification of this program under the terms of
00010 // any other version of the GNU Lesser General Public License is not
00011 // permitted.
00012 // 
00013 // This program is distributed in the hope that it will be useful, but
00014 // WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
00016 // see the GNU Lesser General Public License, Version 2.1, a copy of
00017 // which can be found in the XORP LICENSE.lgpl file.
00018 // 
00019 // XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
00020 // http://xorp.net
00021 
00022 // $XORP: xorp/libxipc/xrl_atom.hh,v 1.23 2008/10/30 20:49:07 pavlin Exp $
00023 
00024 #ifndef __LIBXIPC_XRL_ATOM_HH__
00025 #define __LIBXIPC_XRL_ATOM_HH__
00026 
00027 #include "libxorp/xorp.h"
00028 #include "libxorp/c_format.hh"
00029 #include "libxorp/exceptions.hh"
00030 #include "libxorp/ipv4.hh"
00031 #include "libxorp/ipv4net.hh"
00032 #include "libxorp/ipv6.hh"
00033 #include "libxorp/ipv6net.hh"
00034 #include "libxorp/ipvx.hh"
00035 #include "libxorp/ipvxnet.hh"
00036 #include "libxorp/mac.hh"
00037 
00038 
00039 
00040 
00041 #include "xrl_atom_list.hh"
00042 #include "fp64.h"
00043 
00044 
00045 enum XrlAtomType {
00046     xrlatom_no_type = 0,
00047     xrlatom_int32,
00048     xrlatom_uint32,
00049     xrlatom_ipv4,
00050     xrlatom_ipv4net,
00051     xrlatom_ipv6,
00052     xrlatom_ipv6net,
00053     xrlatom_mac,
00054     xrlatom_text,
00055     xrlatom_list,
00056     xrlatom_boolean,
00057     xrlatom_binary,
00058     xrlatom_int64,
00059     xrlatom_uint64,
00060     xrlatom_fp64,
00061     // ... Your type's unique enumerated name here ...
00062     // Changing order above will break binary compatibility
00063     // ...Don't forget to update xrlatom_start and xrlatom_end below...
00064 
00065     // Bounds for enumerations
00066     xrlatom_start = xrlatom_int32,  // First valid enumerated value
00067     xrlatom_end   = xrlatom_fp64    // Last valid enumerated value
00068 };
00069 
00070 inline XrlAtomType& operator++(XrlAtomType& t)
00071 {
00072     return t = (xrlatom_end == t) ? xrlatom_no_type : XrlAtomType(t + 1);
00073 }
00074 
00078 const char* xrlatom_type_name(const XrlAtomType&);
00079 
00080 class XrlAtom {
00081 public:
00082     // Exceptions
00083     struct NoData : public XorpException {
00084     NoData(const char* file, int line, const string& name) :
00085         XorpException("XrlAtom::NoData", file, line),
00086     _name(name) {}
00087 
00088     const string why() const {
00089         return c_format("Atom name %s has no data", _name.c_str());
00090     }
00091 
00092     private:
00093     string _name;
00094     };
00095 
00096     struct WrongType : public XorpException {
00097     WrongType(const char* file, int line,
00098           const XrlAtomType& actual, const XrlAtomType& expected) :
00099         XorpException("XrlAtom::WrongType", file, line),
00100         _actual(actual), _expected(expected) {}
00101 
00102     const string why() const {
00103         return c_format("Atom type %s (%d) expected %s (%d)",
00104                 xrlatom_type_name(_actual), _actual,
00105                 xrlatom_type_name(_expected), _expected);
00106     }
00107     private:
00108     XrlAtomType _actual;
00109     XrlAtomType _expected;
00110     };
00111 
00112     struct BadName : public XorpException {
00113     BadName(const char* file, int line, const char* name) :
00114         XorpException("XrlAtom::BadName", file, line), _name(name) {}
00115     const string why() const {
00116         return c_format("\"%s\" is not a valid name", _name.c_str());
00117     }
00118     private:
00119     string _name;
00120     };
00121 
00122     XrlAtom() : _type(xrlatom_no_type), _have_data(false), _own(true) {}
00123     ~XrlAtom();
00124 
00125     // type but no data constructors
00126     XrlAtom(XrlAtomType t)
00127     : _type(t), _have_data(false), _own(true) {}
00128 
00129     XrlAtom(const string& name, XrlAtomType t) throw (BadName)
00130     : _type(t), _have_data(false), _own(true) {
00131     set_name(name);
00132     }
00133 
00134     XrlAtom(const char* name, XrlAtomType t) throw (BadName)
00135     : _type(t), _have_data(false), _own(true) {
00136     set_name(name);
00137     }
00138 
00139     XrlAtom(const string& name, XrlAtomType t, const string& serialized_data)
00140     throw (InvalidString);
00141 
00142     XrlAtom(const char* name, XrlAtomType t, const string& serialized_data)
00143     throw (InvalidString);
00144 
00152     explicit XrlAtom(const char*) throw (InvalidString, BadName);
00153 
00154     // int32 constructors
00155     explicit XrlAtom(const int32_t& value)
00156     : _type(xrlatom_int32), _have_data(true), _own(true), _i32val(value) {}
00157 
00158     XrlAtom(const char* name, int32_t value) throw (BadName)
00159     : _type(xrlatom_int32), _have_data(true), _own(true) ,_i32val(value) {
00160     set_name(name);
00161     }
00162 
00163     // bool constructors
00164     explicit XrlAtom(const bool& value)
00165     : _type(xrlatom_boolean), _have_data(true),
00166       _own(true), _boolean(value) {}
00167 
00168     XrlAtom(const char* name, bool value) throw (BadName)
00169     : _type(xrlatom_boolean), _have_data(true),
00170       _own(true), _boolean(value) {
00171     set_name(name);
00172     }
00173 
00174     // uint32 constructors
00175     explicit XrlAtom(const uint32_t& value)
00176     : _type(xrlatom_uint32), _have_data(true), _own(true), _u32val(value) {}
00177 
00178     XrlAtom(const char* name, uint32_t value) throw (BadName)
00179     : _type(xrlatom_uint32), _have_data(true), _own(true), _u32val(value) {
00180     set_name(name);
00181     }
00182 
00183     // ipv4 constructors
00184     explicit XrlAtom(const IPv4& addr)
00185     : _type(xrlatom_ipv4), _have_data(true), _own(true),
00186       _ipv4(addr) {}
00187 
00188     XrlAtom(const char* name, const IPv4& addr) throw (BadName)
00189     : _type(xrlatom_ipv4), _have_data(true), _own(true),
00190       _ipv4(addr) {
00191     set_name(name);
00192     }
00193 
00194     // ipv4net constructors
00195     explicit XrlAtom(const IPv4Net& subnet)
00196         : _type(xrlatom_ipv4net), _have_data(true), _own(true),
00197           _ipv4net(subnet) {}
00198 
00199     XrlAtom(const char* name, const IPv4Net& subnet) throw (BadName)
00200         : _type(xrlatom_ipv4net), _have_data(true), _own(true),
00201           _ipv4net(subnet) {
00202     set_name(name);
00203     }
00204 
00205     // ipv6 constructors
00206     explicit XrlAtom(const IPv6& addr)
00207     : _type(xrlatom_ipv6), _have_data(true), _own(true),
00208     _ipv6(new IPv6(addr)) {}
00209 
00210     XrlAtom(const char* name, const IPv6& addr) throw (BadName)
00211     : _type(xrlatom_ipv6), _have_data(true), _own(true),
00212       _ipv6(new IPv6(addr)) {
00213     set_name(name);
00214     }
00215 
00216     // ipv6 net constructors
00217     explicit XrlAtom(const IPv6Net& subnet)
00218     : _type(xrlatom_ipv6net), _have_data(true), _own(true),
00219     _ipv6net(new IPv6Net(subnet)) {}
00220 
00221     XrlAtom(const char* name, const IPv6Net& subnet) throw (BadName)
00222     : _type(xrlatom_ipv6net), _have_data(true), _own(true),
00223     _ipv6net(new IPv6Net(subnet)) {
00224     set_name(name);
00225     }
00226 
00227     // IPvX constructors - there is no underlying IPvX type
00228     // data is cast to IPv4 or IPv6.
00229     XrlAtom(const char* name, const IPvX& ipvx) throw (BadName)
00230     : _have_data(true), _own(true)
00231     {
00232     set_name(name);
00233     if (ipvx.is_ipv4()) {
00234         _type = xrlatom_ipv4;
00235         _ipv4 = ipvx.get_ipv4();
00236     } else if (ipvx.is_ipv6()) {
00237         _type = xrlatom_ipv6;
00238         _ipv6 = new IPv6(ipvx.get_ipv6());
00239     } else {
00240         abort();
00241     }
00242     }
00243 
00244     // IPvXNet constructors - there is no underlying IPvXNet type
00245     // data is cast to IPv4Net or IPv6Net.
00246     XrlAtom(const char* name, const IPvXNet& ipvxnet) throw (BadName)
00247     : _have_data(true), _own(true)
00248     {
00249     set_name(name);
00250     if (ipvxnet.is_ipv4()) {
00251         _type = xrlatom_ipv4net;
00252         _ipv4net = ipvxnet.get_ipv4net();
00253     } else if (ipvxnet.is_ipv6()) {
00254         _type = xrlatom_ipv6net;
00255         _ipv6net = new IPv6Net(ipvxnet.get_ipv6net());
00256     } else {
00257         abort();
00258     }
00259     }
00260 
00261     // mac constructors
00262     explicit XrlAtom(const Mac& mac)
00263     : _type(xrlatom_mac), _have_data(true), _own(true),
00264     _mac(new Mac(mac)) {}
00265 
00266     XrlAtom(const char* name, const Mac& mac) throw (BadName)
00267     : _type(xrlatom_mac), _have_data(true), _own(true),
00268     _mac(new Mac(mac)) {
00269     set_name(name);
00270     }
00271 
00272     // text constructors
00273     explicit XrlAtom(const string& txt)
00274     : _type(xrlatom_text), _have_data(true), _own(true),
00275         _text(new string(txt)) {}
00276 
00277     XrlAtom(const char* name, const string& txt) throw (BadName)
00278     : _type(xrlatom_text), _have_data(true), _own(true),
00279         _text(new string(txt)) {
00280     set_name(name);
00281     }
00282 
00283    // list constructors
00284     explicit XrlAtom(const XrlAtomList& l)
00285     : _type(xrlatom_list), _have_data(true), _own(true),
00286     _list(new XrlAtomList(l)) {}
00287 
00288     XrlAtom(const char* name, const XrlAtomList& l) throw (BadName)
00289     : _type(xrlatom_list), _have_data(true), _own(true),
00290     _list(new XrlAtomList(l)) {
00291     set_name(name);
00292     }
00293 
00294     // binary
00295     XrlAtom(const char* name, const vector<uint8_t>& data)
00296     : _type(xrlatom_binary), _have_data(true), _own(true),
00297       _binary(new vector<uint8_t>(data)) {
00298     set_name(name);
00299     }
00300 
00301     XrlAtom(const char* name, const uint8_t* data, size_t data_bytes)
00302     : _type(xrlatom_binary), _have_data(true), _own(true),
00303       _binary(new vector<uint8_t>(data, data + data_bytes)) {
00304     set_name(name);
00305     }
00306 
00307     XrlAtom(const vector<uint8_t>& data)
00308     : _type(xrlatom_binary), _have_data(true), _own(true),
00309       _binary(new vector<uint8_t>(data)) {}
00310 
00311     XrlAtom(const uint8_t* data, size_t data_bytes)
00312     : _type(xrlatom_binary), _have_data(true), _own(true),
00313       _binary(new vector<uint8_t>(data, data + data_bytes)) {}
00314 
00315     // int64 constructors
00316     explicit XrlAtom(const int64_t& value)
00317     : _type(xrlatom_int64), _have_data(true), _own(true), _i64val(value) {}
00318 
00319     XrlAtom(const char* name, int64_t value) throw (BadName)
00320     : _type(xrlatom_int64), _have_data(true), _own(true), _i64val(value) {
00321     set_name(name);
00322     }
00323 
00324     // uint64 constructors
00325     explicit XrlAtom(const uint64_t& value)
00326     : _type(xrlatom_uint64), _have_data(true), _own(true), _u64val(value) {}
00327 
00328     XrlAtom(const char* name, uint64_t value) throw (BadName)
00329     : _type(xrlatom_uint64), _have_data(true), _own(true), _u64val(value) {
00330     set_name(name);
00331     }
00332 
00333 
00334     // fp64 constructors
00335     explicit XrlAtom(const fp64_t& value)
00336     : _type(xrlatom_fp64), _have_data(true), _own(true), _fp64val(value) {}
00337 
00338     XrlAtom(const char* name, fp64_t value) throw (BadName)
00339     : _type(xrlatom_fp64), _have_data(true), _own(true), _fp64val(value) {
00340     set_name(name);
00341     }
00342 
00343 
00344     // ... Your type's constructors here ...
00345 
00346     // Copy operations
00347     XrlAtom(const XrlAtom& x)
00348     : _type(xrlatom_no_type), _have_data(false), _own(true) {
00349     copy(x);
00350     }
00351     XrlAtom& operator=(const XrlAtom& x) {
00352     discard_dynamic(); copy(x); return *this;
00353     }
00354     void copy(const XrlAtom& x);
00355 
00356     // Accessor operations
00357     const string& name() const { return _atom_name; }
00358     void set_name(const string& n) throw (BadName) { set_name (n.c_str()); }
00359 
00360     string str() const;
00361     const char* type_name() const;
00362     const string value() const;
00363 
00364     const bool&     has_data() const { return _have_data; }
00365     const XrlAtomType&  type() const { return _type; }
00366 
00367     // The following accessors may throw accessor exceptions...
00368     const bool&        boolean() const throw (NoData, WrongType);
00369     const int32_t&     int32() const throw (NoData, WrongType);
00370     const uint32_t&    uint32() const throw (NoData, WrongType);
00371     const IPv4&        ipv4() const throw (NoData, WrongType);
00372     const IPv4Net&         ipv4net() const throw (NoData, WrongType);
00373     const IPv6&        ipv6() const throw (NoData, WrongType);
00374     const IPv6Net&     ipv6net() const throw (NoData, WrongType);
00375     const IPvX         ipvx() const throw (NoData, WrongType);
00376     const IPvXNet      ipvxnet() const throw (NoData, WrongType);
00377     const Mac&         mac() const throw (NoData, WrongType);
00378     const string&      text() const throw (NoData, WrongType);
00379     const XrlAtomList&     list() const throw (NoData, WrongType);
00380     const vector<uint8_t>& binary() const throw (NoData, WrongType);
00381     const int64_t&     int64() const throw (NoData, WrongType);
00382     const uint64_t&    uint64() const throw (NoData, WrongType);
00383     const fp64_t&      fp64() const throw (NoData, WrongType);
00384 
00385     // ... Your type's accessor method here ...
00386 
00387     // set methods
00388 #define SET(type, var, p)           \
00389     void set(const type& arg)           \
00390     {                       \
00391     abandon_data();             \
00392                         \
00393     type& a = const_cast<type&>(arg);   \
00394     var = p a;              \
00395     }
00396 
00397     SET(int32_t, _i32val, )
00398     SET(uint32_t, _u32val, )
00399     SET(int64_t, _i64val, )
00400     SET(uint64_t, _u64val, )
00401     SET(bool, _boolean, )
00402     SET(IPv6, _ipv6, &)
00403     SET(IPv6Net, _ipv6net, &)
00404     SET(Mac, _mac, &)
00405     SET(string, _text, &)
00406     SET(XrlAtomList, _list, &)
00407     SET(vector<uint8_t>, _binary, &);
00408     SET(fp64_t, _fp64val, )
00409 #undef SET
00410 
00411     void set(const IPv4& v) {
00412     abandon_data();
00413     _ipv4 = v;
00414     }
00415 
00416     void set(const IPv4Net& v) {
00417     abandon_data();
00418     _ipv4net = v;
00419     }
00420 
00421     // Equality tests
00422     bool operator==(const XrlAtom& x) const;
00423 
00424     // Binary packing and unpacking operations
00425     bool packed_bytes_fixed() const;
00426     size_t packed_bytes() const;
00427     size_t pack(uint8_t* buffer, size_t bytes_available) const;
00428 
00429     size_t unpack(const uint8_t* buffer, size_t buffer_bytes);
00430 
00431     static bool valid_type(const string& s);
00432     static bool valid_name(const string& s);
00433     static XrlAtomType lookup_type(const string& s) {
00434     return resolve_type_c_str(s.c_str());
00435     }
00436 
00437     static size_t peek_text(const char*& t, uint32_t& tl,
00438                 const uint8_t* buf, size_t len);
00439 
00440 private:
00441 
00442     void discard_dynamic();
00443     void abandon_data();
00444     void type_and_data_okay(const XrlAtomType& t) const
00445     throw (NoData, WrongType);
00446 
00447     void set_name(const char *n) throw (BadName);
00448     static XrlAtomType resolve_type_c_str(const char*);
00449     ssize_t data_from_c_str(const char* c_str);
00450 
00451     size_t pack_name(uint8_t* buffer) const;
00452     size_t pack_boolean(uint8_t* buffer) const;
00453     size_t pack_uint32(uint8_t* buffer) const;
00454     size_t pack_ipv4(uint8_t* buffer) const;
00455     size_t pack_ipv4net(uint8_t* buffer) const;
00456     size_t pack_ipv6(uint8_t* buffer) const;
00457     size_t pack_ipv6net(uint8_t* buffer) const;
00458     size_t pack_mac(uint8_t* buffer) const;
00459     size_t pack_text(uint8_t* buffer) const;
00460     size_t pack_list(uint8_t* buffer, size_t buffer_bytes) const;
00461     size_t pack_binary(uint8_t* buffer) const;
00462     size_t pack_uint64(uint8_t* buffer) const;
00463     size_t pack_fp64(uint8_t* buffer) const;
00464 
00465     size_t unpack_name(const uint8_t* buffer, size_t buffer_bytes)
00466     throw (BadName);
00467     size_t unpack_boolean(const uint8_t* buffer);
00468     size_t unpack_uint32(const uint8_t* buffer);
00469     size_t unpack_ipv4(const uint8_t* buffer);
00470     size_t unpack_ipv4net(const uint8_t* buffer);
00471     size_t unpack_ipv6(const uint8_t* buffer);
00472     size_t unpack_ipv6net(const uint8_t* buffer);
00473     size_t unpack_mac(const uint8_t* buffer, size_t buffer_bytes);
00474     size_t unpack_text(const uint8_t* buffer, size_t buffer_bytes);
00475     size_t unpack_list(const uint8_t* buffer, size_t buffer_bytes);
00476     size_t unpack_binary(const uint8_t* buffer, size_t buffer_bytes);
00477     size_t unpack_uint64(const uint8_t* buffer);
00478     size_t unpack_fp64(const uint8_t* buffer);
00479 
00480 private:
00481     XrlAtomType _type;
00482     bool    _have_data;
00483     string  _atom_name;
00484     bool    _own;
00485 
00486     union {
00487     bool         _boolean;
00488         int32_t      _i32val;
00489         uint32_t     _u32val;
00490         IPv6*        _ipv6;
00491         IPv6Net*     _ipv6net;
00492         Mac*         _mac;
00493         string*      _text;
00494     XrlAtomList*     _list;
00495     vector<uint8_t>* _binary;
00496         int64_t      _i64val;
00497         uint64_t     _u64val;
00498         fp64_t           _fp64val;
00499 
00500         // ... Your type here, if it's more than sizeof(uintptr_t) bytes,
00501     // use a pointer ...
00502     } ;
00503 
00504     // Can't put this in a union, evidently.
00505     IPv4             _ipv4;
00506     IPv4Net              _ipv4net;
00507 };
00508 
00509 // XrlAtomSpell is a placeholder class for Xrl mapping
00510 // It used to hold the name:type of an atom whose value we
00511 // wish to refer to.
00512 class XrlAtomSpell {
00513 public:
00514     XrlAtomSpell(const XrlAtom& xa, const string& spell) :
00515     _xa(xa), _spell(spell) {}
00516     XrlAtomSpell(const string&      name,
00517          const XrlAtomType& type,
00518          const string&      m)
00519     : _xa(XrlAtom(name, type)), _spell(m) {}
00520 #ifdef XORP_USE_USTL
00521     XrlAtomSpell() { }
00522 #endif
00523     const string& atom_name() const { return _xa.name(); }
00524     const XrlAtomType& atom_type() const { return _xa.type(); }
00525     const XrlAtom& atom() const { return _xa; }
00526     const string& spell() const { return _spell; }
00527 
00528 protected:
00529     XrlAtom _xa;
00530     string  _spell;
00531 };
00532 
00533 #endif // __LIBXIPC_XRL_ATOM_HH__
 All Classes Namespaces Functions Variables Typedefs Enumerations