<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/> <title>libnl: Object API</title> <link href="tabs.css" rel="stylesheet" type="text/css"/> <link href="doxygen.css" rel="stylesheet" type="text/css"/> </head> <body> <!-- Generated by Doxygen 1.7.3 --> <div id="top"> <div id="titlearea"> <table cellspacing="0" cellpadding="0"> <tbody> <tr style="height: 56px;"> <td style="padding-left: 0.5em;"> <div id="projectname">libnl <span id="projectnumber">1.1</span></div> </td> </tr> </tbody> </table> </div> <div id="navrow1" class="tabs"> <ul class="tablist"> <li><a href="index.html"><span>Main Page</span></a></li> <li><a href="modules.html"><span>Modules</span></a></li> <li><a href="annotated.html"><span>Data Structures</span></a></li> <li><a href="files.html"><span>Files</span></a></li> </ul> </div> </div> <div class="header"> <div class="summary"> <a href="#nested-classes">Data Structures</a> | <a href="#define-members">Defines</a> </div> <div class="headertitle"> <h1>Object API</h1> </div> <div class="ingroups"><a class="el" href="group__object.html">Object</a></div></div> <div class="contents"> <table class="memberdecls"> <tr><td colspan="2"><h2><a name="nested-classes"></a> Data Structures</h2></td></tr> <tr><td class="memItemLeft" align="right" valign="top">struct  </td><td class="memItemRight" valign="bottom"><a class="el" href="structnl__object__ops.html">nl_object_ops</a></td></tr> <tr><td class="mdescLeft"> </td><td class="mdescRight">Object Operations. <a href="structnl__object__ops.html#_details">More...</a><br/></td></tr> <tr><td colspan="2"><h2><a name="define-members"></a> Defines</h2></td></tr> <tr><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__object__api.html#ga0f84d461252a52ed33e307432bd0b3f8">NLHDR_COMMON</a></td></tr> <tr><td class="mdescLeft"> </td><td class="mdescRight">Common Object Header. <a href="#ga0f84d461252a52ed33e307432bd0b3f8"></a><br/></td></tr> <tr><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__object__api.html#gaaea44dd0350eb403226ba5edba05ecbc">AVAILABLE</a>(A, B, ATTR)   (((A)->ce_mask & (B)->ce_mask) & (ATTR))</td></tr> <tr><td class="mdescLeft"> </td><td class="mdescRight">Return true if attribute is available in both objects. <a href="#gaaea44dd0350eb403226ba5edba05ecbc"></a><br/></td></tr> <tr><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__object__api.html#gafefec474eb34fd780b5233b6289773e9">ATTR_MISMATCH</a>(A, B, ATTR, EXPR)   (!AVAILABLE(A, B, ATTR) || (EXPR))</td></tr> <tr><td class="mdescLeft"> </td><td class="mdescRight">Return true if attributes mismatch. <a href="#gafefec474eb34fd780b5233b6289773e9"></a><br/></td></tr> <tr><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__object__api.html#ga726810b073cacc182dc6e2ea6cc2f14a">ATTR_DIFF</a>(LIST, ATTR, A, B, EXPR)</td></tr> <tr><td class="mdescLeft"> </td><td class="mdescRight">Return attribute bit if attribute does not match. <a href="#ga726810b073cacc182dc6e2ea6cc2f14a"></a><br/></td></tr> </table> <hr/><a name="_details"></a><h2>Detailed Description</h2> <dl class="user"><dt><b>1) Object Definition</b></dt><dd><div class="fragment"><pre class="fragment"> <span class="comment">// Define your object starting with the common object header</span> <span class="keyword">struct </span>my_obj { <a class="code" href="group__object__api.html#ga0f84d461252a52ed33e307432bd0b3f8" title="Common Object Header.">NLHDR_COMMON</a> <span class="keywordtype">int</span> my_data; }; <span class="comment">// Fill out the object operations structure</span> <span class="keyword">struct </span><a class="code" href="structnl__object__ops.html" title="Object Operations.">nl_object_ops</a> my_ops = { .<a class="code" href="structnl__object__ops.html#a5225584343fe711642303e000b036ee9" title="Unique name of object type.">oo_name</a> = <span class="stringliteral">"my_obj"</span>, .oo_size = <span class="keyword">sizeof</span>(<span class="keyword">struct </span>my_obj), }; <span class="comment">// At this point the object can be allocated, you may want to provide a</span> <span class="comment">// separate _alloc() function to ease allocting objects of this kind.</span> <span class="keyword">struct </span>nl_object *obj = <a class="code" href="group__object.html#ga9c1f2fd887d8325839f452879cdf982a" title="Allocate a new object of kind specified by the operations handle.">nl_object_alloc</a>(&my_ops); <span class="comment">// And release it again...</span> <a class="code" href="group__object.html#ga9905da094bf4c03cf4ac78aeaa86a12b" title="Release a reference from an object.">nl_object_put</a>(obj); </pre></div></dd></dl> <dl class="user"><dt><b>2) Allocating additional data</b></dt><dd><div class="fragment"><pre class="fragment"> <span class="comment">// You may require to allocate additional data and store it inside</span> <span class="comment">// object, f.e. assuming there is a field `ptr'.</span> <span class="keyword">struct </span>my_obj { <a class="code" href="group__object__api.html#ga0f84d461252a52ed33e307432bd0b3f8" title="Common Object Header.">NLHDR_COMMON</a> <span class="keywordtype">void</span> * ptr; }; <span class="comment">// And at some point you may assign allocated data to this field:</span> my_obj->ptr = calloc(1, ...); <span class="comment">// In order to not introduce any memory leaks you have to release</span> <span class="comment">// this data again when the last reference is given back.</span> <span class="keyword">static</span> <span class="keywordtype">void</span> my_obj_free_data(<span class="keyword">struct</span> nl_object *obj) { <span class="keyword">struct </span>my_obj *my_obj = nl_object_priv(obj); free(my_obj->ptr); } <span class="comment">// Also when the object is cloned, you must ensure for your pointer</span> <span class="comment">// stay valid even if one of the clones is freed by either making</span> <span class="comment">// a clone as well or increase the reference count.</span> <span class="keyword">static</span> <span class="keywordtype">int</span> my_obj_clone(<span class="keyword">struct</span> nl_object *src, <span class="keyword">struct</span> nl_object *dst) { <span class="keyword">struct </span>my_obj *my_src = nl_object_priv(src); <span class="keyword">struct </span>my_obj *my_dst = nl_object_priv(dst); <span class="keywordflow">if</span> (src->ptr) { dst->ptr = calloc(1, ...); memcpy(dst->ptr, src->ptr, ...); } } <span class="keyword">struct </span><a class="code" href="structnl__object__ops.html" title="Object Operations.">nl_object_ops</a> my_ops = { ... .<a class="code" href="structnl__object__ops.html#a38797e8754a31bb259120ef9101bbb0a" title="Destructor function.">oo_free_data</a> = my_obj_free_data, .oo_clone = my_obj_clone, }; </pre></div></dd></dl> <dl class="user"><dt><b>3) Object Dumping</b></dt><dd><div class="fragment"><pre class="fragment"> <span class="keyword">static</span> <span class="keywordtype">int</span> my_obj_dump_detailed(<span class="keyword">struct</span> nl_object *obj, <span class="keyword">struct</span> <a class="code" href="structnl__dump__params.html" title="Dumping parameters.">nl_dump_params</a> *params) { <span class="keyword">struct </span>my_obj *my_obj = nl_object_priv(obj); <span class="keywordtype">int</span> line = 1; <span class="comment">// We will print at least one line for sure</span> <span class="comment">// It is absolutely essential to use nl_dump() when printing</span> <span class="comment">// any text to make sure the dumping parameters are respected.</span> <a class="code" href="group__utils.html#ga527075856a5427170865a6f409298cdf" title="Dump a formatted character string.">nl_dump</a>(params, <span class="stringliteral">"Obj Integer: %d\n"</span>, my_obj->my_int); <span class="comment">// Before we can dump the next line, make sure to prefix</span> <span class="comment">// this line correctly.</span> <a class="code" href="group__utils.html#ga8d036ba05aa233203e8d7fb79f925c2c" title="Handle a new line while dumping.">nl_new_line</a>(params, line++); <span class="comment">// You may also split a line into multiple nl_dump() calls.</span> <a class="code" href="group__utils.html#ga527075856a5427170865a6f409298cdf" title="Dump a formatted character string.">nl_dump</a>(params, <span class="stringliteral">"String: %s "</span>, my_obj->my_string); <a class="code" href="group__utils.html#ga527075856a5427170865a6f409298cdf" title="Dump a formatted character string.">nl_dump</a>(params, <span class="stringliteral">"String-2: %s\n"</span>, my_obj->another_string); <span class="comment">// Return the number of lines dumped</span> <span class="keywordflow">return</span> line; } <span class="keyword">struct </span><a class="code" href="structnl__object__ops.html" title="Object Operations.">nl_object_ops</a> my_ops = { ... .<a class="code" href="structnl__object__ops.html#a0a3d28af43d7f75cda0b8cbc23ad7432" title="Dumping functions.">oo_dump</a>[<a class="code" href="group__utils.html#ggacfb5566c73f0965c5241d7d49bc717e9a1445106c7af529b2c99ee289fbcd3179" title="Dump all attributes but no statistics.">NL_DUMP_FULL</a>] = my_obj_dump_detailed, }; </pre></div></dd></dl> <dl class="user"><dt><b>4) Object Attributes</b></dt><dd><div class="fragment"><pre class="fragment"> <span class="comment">// The concept of object attributes is optional but can ease the typical</span> <span class="comment">// case of objects that have optional attributes, e.g. a route may have a</span> <span class="comment">// nexthop assigned but it is not required to.</span> <span class="comment">// The first step to define your object specific bitmask listing all</span> <span class="comment">// attributes</span> <span class="preprocessor"> #define MY_ATTR_FOO (1<<0)</span> <span class="preprocessor"></span><span class="preprocessor"> #define MY_ATTR_BAR (1<<1)</span> <span class="preprocessor"></span> <span class="comment">// When assigning an optional attribute to the object, make sure</span> <span class="comment">// to mark its availability.</span> my_obj->foo = 123123; my_obj->ce_mask |= MY_ATTR_FOO; <span class="comment">// At any time you may use this mask to check for the availability</span> <span class="comment">// of the attribute, e.g. while dumping</span> <span class="keywordflow">if</span> (my_obj->ce_mask & MY_ATTR_FOO) <a class="code" href="group__utils.html#ga527075856a5427170865a6f409298cdf" title="Dump a formatted character string.">nl_dump</a>(params, <span class="stringliteral">"foo %d "</span>, my_obj->foo); <span class="comment">// One of the big advantages of this concept is that it allows for</span> <span class="comment">// standardized comparisons which make it trivial for caches to</span> <span class="comment">// identify unique objects by use of unified comparison functions.</span> <span class="comment">// In order for it to work, your object implementation must provide</span> <span class="comment">// a comparison function and define a list of attributes which</span> <span class="comment">// combined together make an object unique.</span> <span class="keyword">static</span> <span class="keywordtype">int</span> my_obj_compare(<span class="keyword">struct</span> nl_object *_a, <span class="keyword">struct</span> nl_object *_b, uint32_t attrs, <span class="keywordtype">int</span> flags) { <span class="keyword">struct </span>my_obj *a = nl_object_priv(_a): struct my_obj *b = nl_object_priv(_b): int diff = 0; <span class="comment">// We help ourselves in defining our own DIFF macro which will</span> <span class="comment">// call ATTR_DIFF() on both objects which will make sure to only</span> <span class="comment">// compare the attributes if required.</span> <span class="preprocessor"> #define MY_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MY_ATTR_##ATTR, a, b, EXPR)</span> <span class="preprocessor"></span> <span class="comment">// Call our own diff macro for each attribute to build a bitmask</span> <span class="comment">// representing the attributes which mismatch.</span> diff |= MY_DIFF(FOO, a->foo != b->foo) diff |= MY_DIFF(BAR, strcmp(a->bar, b->bar)) return diff; } <span class="comment">// In order to identify identical objects with differing attributes</span> <span class="comment">// you must specify the attributes required to uniquely identify</span> <span class="comment">// your object. Make sure to not include too many attributes, this</span> <span class="comment">// list is used when caches look for an old version of an object.</span> struct <a class="code" href="structnl__object__ops.html" title="Object Operations.">nl_object_ops</a> my_ops = { ... .oo_id_attrs = MY_ATTR_FOO, .oo_compare = my_obj_compare, }; </pre></div> </dd></dl> <hr/><h2>Define Documentation</h2> <a class="anchor" id="ga0f84d461252a52ed33e307432bd0b3f8"></a><!-- doxytag: member="object-api.h::NLHDR_COMMON" ref="ga0f84d461252a52ed33e307432bd0b3f8" args="" --> <div class="memitem"> <div class="memproto"> <table class="memname"> <tr> <td class="memname">#define NLHDR_COMMON</td> </tr> </table> </div> <div class="memdoc"> <b>Value:</b><div class="fragment"><pre class="fragment"><span class="keywordtype">int</span> ce_refcnt; \ <span class="keyword">struct </span><a class="code" href="structnl__object__ops.html" title="Object Operations.">nl_object_ops</a> * ce_ops; \ <span class="keyword">struct </span>nl_cache * ce_cache; \ <span class="keyword">struct </span><a class="code" href="structnl__list__head.html">nl_list_head</a> ce_list; \ <span class="keywordtype">int</span> ce_msgtype; \ <span class="keywordtype">int</span> ce_flags; \ uint32_t ce_mask; </pre></div><p>This macro must be included as first member in every object definition to allow objects to be cached. </p> <p>Definition at line <a class="el" href="object-api_8h_source.html#l00188">188</a> of file <a class="el" href="object-api_8h_source.html">object-api.h</a>.</p> </div> </div> <a class="anchor" id="gaaea44dd0350eb403226ba5edba05ecbc"></a><!-- doxytag: member="object-api.h::AVAILABLE" ref="gaaea44dd0350eb403226ba5edba05ecbc" args="(A, B, ATTR)" --> <div class="memitem"> <div class="memproto"> <table class="memname"> <tr> <td class="memname">#define AVAILABLE</td> <td>(</td> <td class="paramtype"> </td> <td class="paramname">A, </td> </tr> <tr> <td class="paramkey"></td> <td></td> <td class="paramtype"> </td> <td class="paramname">B, </td> </tr> <tr> <td class="paramkey"></td> <td></td> <td class="paramtype"> </td> <td class="paramname">ATTR </td> </tr> <tr> <td></td> <td>)</td> <td></td><td>   (((A)->ce_mask & (B)->ce_mask) & (ATTR))</td> </tr> </table> </div> <div class="memdoc"> <dl><dt><b>Parameters:</b></dt><dd> <table class="params"> <tr><td class="paramname">A</td><td>an object </td></tr> <tr><td class="paramname">B</td><td>another object </td></tr> <tr><td class="paramname">ATTR</td><td>attribute bit</td></tr> </table> </dd> </dl> <dl class="return"><dt><b>Returns:</b></dt><dd>True if the attribute is available, otherwise false is returned. </dd></dl> <p>Definition at line <a class="el" href="object-api_8h_source.html#l00205">205</a> of file <a class="el" href="object-api_8h_source.html">object-api.h</a>.</p> </div> </div> <a class="anchor" id="gafefec474eb34fd780b5233b6289773e9"></a><!-- doxytag: member="object-api.h::ATTR_MISMATCH" ref="gafefec474eb34fd780b5233b6289773e9" args="(A, B, ATTR, EXPR)" --> <div class="memitem"> <div class="memproto"> <table class="memname"> <tr> <td class="memname">#define ATTR_MISMATCH</td> <td>(</td> <td class="paramtype"> </td> <td class="paramname">A, </td> </tr> <tr> <td class="paramkey"></td> <td></td> <td class="paramtype"> </td> <td class="paramname">B, </td> </tr> <tr> <td class="paramkey"></td> <td></td> <td class="paramtype"> </td> <td class="paramname">ATTR, </td> </tr> <tr> <td class="paramkey"></td> <td></td> <td class="paramtype"> </td> <td class="paramname">EXPR </td> </tr> <tr> <td></td> <td>)</td> <td></td><td>   (!AVAILABLE(A, B, ATTR) || (EXPR))</td> </tr> </table> </div> <div class="memdoc"> <dl><dt><b>Parameters:</b></dt><dd> <table class="params"> <tr><td class="paramname">A</td><td>an object </td></tr> <tr><td class="paramname">B</td><td>another object </td></tr> <tr><td class="paramname">ATTR</td><td>attribute bit </td></tr> <tr><td class="paramname">EXPR</td><td>Comparison expression</td></tr> </table> </dd> </dl> <p>This function will check if the attribute in question is available in both objects, if not this will count as a mismatch.</p> <p>If available the function will execute the expression which must return true if the attributes mismatch.</p> <dl class="return"><dt><b>Returns:</b></dt><dd>True if the attribute mismatch, or false if they match. </dd></dl> <p>Definition at line <a class="el" href="object-api_8h_source.html#l00222">222</a> of file <a class="el" href="object-api_8h_source.html">object-api.h</a>.</p> </div> </div> <a class="anchor" id="ga726810b073cacc182dc6e2ea6cc2f14a"></a><!-- doxytag: member="object-api.h::ATTR_DIFF" ref="ga726810b073cacc182dc6e2ea6cc2f14a" args="(LIST, ATTR, A, B, EXPR)" --> <div class="memitem"> <div class="memproto"> <table class="memname"> <tr> <td class="memname">#define ATTR_DIFF</td> <td>(</td> <td class="paramtype"> </td> <td class="paramname">LIST, </td> </tr> <tr> <td class="paramkey"></td> <td></td> <td class="paramtype"> </td> <td class="paramname">ATTR, </td> </tr> <tr> <td class="paramkey"></td> <td></td> <td class="paramtype"> </td> <td class="paramname">A, </td> </tr> <tr> <td class="paramkey"></td> <td></td> <td class="paramtype"> </td> <td class="paramname">B, </td> </tr> <tr> <td class="paramkey"></td> <td></td> <td class="paramtype"> </td> <td class="paramname">EXPR </td> </tr> <tr> <td></td> <td>)</td> <td></td><td></td> </tr> </table> </div> <div class="memdoc"> <b>Value:</b><div class="fragment"><pre class="fragment">({ <span class="keywordtype">int</span> diff = 0; \ <span class="keywordflow">if</span> (((LIST) & (ATTR)) && <a class="code" href="group__object__api.html#gafefec474eb34fd780b5233b6289773e9" title="Return true if attributes mismatch.">ATTR_MISMATCH</a>(A, B, ATTR, EXPR)) \ diff = ATTR; \ diff; }) </pre></div><dl><dt><b>Parameters:</b></dt><dd> <table class="params"> <tr><td class="paramname">LIST</td><td>list of attributes to be compared </td></tr> <tr><td class="paramname">ATTR</td><td>attribute bit </td></tr> <tr><td class="paramname">A</td><td>an object </td></tr> <tr><td class="paramname">B</td><td>another object </td></tr> <tr><td class="paramname">EXPR</td><td>Comparison expression</td></tr> </table> </dd> </dl> <p>This function will check if the attribute in question is available in both objects, if not this will count as a mismatch.</p> <p>If available the function will execute the expression which must return true if the attributes mismatch.</p> <p>In case the attributes mismatch, the attribute is returned, otherwise 0 is returned.</p> <div class="fragment"><pre class="fragment"> diff |= <a class="code" href="group__object__api.html#ga726810b073cacc182dc6e2ea6cc2f14a" title="Return attribute bit if attribute does not match.">ATTR_DIFF</a>(attrs, MY_ATTR_FOO, a, b, a->foo != b->foo); </pre></div> <p>Definition at line <a class="el" href="object-api_8h_source.html#l00245">245</a> of file <a class="el" href="object-api_8h_source.html">object-api.h</a>.</p> </div> </div> </div> <hr class="footer"/><address class="footer"><small>Generated on Mon Mar 21 2011 for libnl by  <a href="http://www.doxygen.org/index.html"> <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.7.3 </small></address> </body> </html>