1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
|
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Redland RDF Application Framework - Hacking Redland librdf</title>
<style type="text/css">
<!--
pre
{
margin: 1em 4em 1em 4em;
background-color: #eee;
padding: 0.5em;
border-color: #006;
border-width: 1px;
border-style: dotted;
}
-->
</style>
</head>
<body>
<h1>Hacking Redland librdf</h1>
<p>2011-08-23</p>
<p><a href="http://www.dajobe.org/">Dave Beckett</a></p>
<h2>Commits</h2>
<p>Should be:</p>
<ul>
<li>Licensed with the same license as Redland librdf.</li>
<li>Patches in GNU <code>diff -u</code> unifed context format preferred.</li>
<li>Include tests if they add new features.</li>
</ul>
<h2>Code Style</h2>
<p>Do not make large commits that only change code style unless you have
previously had this agreed or it is in code under major refactoring
where a diff is not a large concern. There is always <code>diff -b</code> when
large code style (whitespace) changes are made.</p>
<h3>Indenting</h3>
<p>2 spaces. No tabs.</p>
<p>All code must be wrapped to 80 chars as far as is possible. Function
definitions or calls should indent the parameters to the left <code>(</code>.</p>
<p>Redland libraries use very long function names following the naming
convention which can make linebreaking very hard. In this case,
indent function parameters on new lines 4 spaces after the function
name like this:</p>
<pre><code>
var = function_name_with_very_long_name_that_is_hard_to_wrap_args(
argument1_with_very_long_name_or_expression,
argument2,
..)
</code></pre>
<p>Use no space between a keyword followed by braces argument.
For example, use <code>if(cond)</code> rather than <code>if (cond)</code> (ditto for
while, do etc.) and
<code>functionname(...)</code> rather than <code>functionname (...)</code> in
both definition and calls of functions.</p>
<p>There is nothing wrong with introducing a variable to break up a very
long function call argument.</p>
<h3>Expressions</h3>
<p>Put spaces around operators in expressions, assignments, tests, conditions</p>
<p>GOOD:</p>
<ul>
<li><code>a += 2 * x</code></li>
<li><code>if(a < 2)</code></li>
</ul>
<p>BAD:</p>
<ul>
<li><code>a+=2*x</code></li>
<li><code>if(a<2)</code></li>
</ul>
<p>When comparing to <code>0</code> or a <code>NULL</code> pointer, use the idiomatic form
that has no comparison.</p>
<p>GOOD:</p>
<ul>
<li><code>if(!ptr)</code></li>
<li><code>if(!index)</code></li>
</ul>
<p>BAD:</p>
<ul>
<li><code>if(ptr == NULL)</code></li>
<li><code>if(index == 0)</code></li>
<li><code>if(0 == index)</code></li>
</ul>
<p>When comparing a variable to a constant, the code has currently used
<code>if(var == constant)</code> rather than the slightly safer, and easier to
compile check, <code>if(constant == var)</code>.</p>
<h3>Blocks</h3>
<p>In general add {}s around blocks in if else chains when one of the blocks
has more than 1 line of code. Try not to mix, but the final case if it
is one line, can be braceless.</p>
<pre><code>
if(var == 1) {
... multiple lines of code ...
} else {
... multiple lines of code ...
}
</code></pre>
<p>or</p>
<pre><code>
if(var == 1)
... one line of code
else
... one line of code
</code></pre>
<p>or</p>
<pre><code>
if(var == 1) {
... multiple lines of code ...
} else if(var == 2) {
... multiple lines of code and / or more if conditions ...
} else
... one line of code ...
</code></pre>
<h3>Switches</h3>
<p>If using if else chains on an enumeration, don't do that, use a
<code>switch()</code> which GCC can use to find missing cases when they get added.</p>
<pre><code>
switch(enum_var) {
case ENUM_1:
... code ...
break;
case ENUM_2:
... code ...
break;
case ENUM_DONT_CARE:
default:
... code ...
break;
}
</code></pre>
<p>There should ALWAYS be a <code>default:</code> case.</p>
<h3>Functions</h3>
<p>Declare functions in this format:</p>
<pre><code>
returntype
functionname(type1 param1, type2 param2, ...)
{
type3 var1;
type4 var2;
... first line of code ...
tidy:
... cleanup code...
return value;
}
</code></pre>
<p>Notes:</p>
<ul>
<li>Declare one variable per line</li>
<li>Declare all variables at the top of the function (K&R C style)</li>
<li>You may declare variables in inner <code>{}</code> blocks. The
form <code>if(1) { ... var decls ...; more code }</code> may be used but
a code rewrite is preferable.</li>
<li>If a label is used it <em>MUST</em> be used only for cleanup, and going
forward in the code to the end of the function.</li>
<li>Multiple <code>return</code> are allowed but for obvious error or result
returns. Do not twist the code to enable a single return.</li>
<li><code>goto</code> may be used for resource cleanup and result return
where control flow only goes forward.</li>
</ul>
<h3>C Pre-Processor (CPP) Macros</h3>
<p>Always define macros for internal constants and name the macros with
the library prefix followed by a descriptive name in ALL CAPS such as:</p>
<pre><code>
#define LIBRDF_FOOBAR_BUFFER_SIZE 1234
</code></pre>
<p>When evaluating macro symbols that may be undefined, always check the
symbol is defined first. Like this:</p>
<pre><code>
#if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 42
... do complex debugging stuff ...
#endif
</code></pre>
<p>This is not needed for macros that are known to be defined, such as those
checked by <code>configure</code> e.g.</p>
<pre><code>
#if RAPTOR_VERSION_DECIMAL > 20100
... do stuff that requires a raptor2 version 2.1.0 or newer ...
#endif
</code></pre>
<p>since the above would be checked implicitly by <code>configure</code> using
<code>pkg-config(1)</code> to validate Raptor 2 is present before getting to the
code that tries to evaluate the value from <code>raptor2.h</code>.</p>
<p>The debug macros that are used for printing out values when debugging
is enabled do not need protection by <code>#if</code> or <code>#ifdef</code> and should be
used like this:</p>
<pre><code>
LIBRDF_DEBUG1("Something wonderful happened\n");
LIBRDF_DEBUG2("Something %s happened\n", happening);
</code></pre>
<h3>Memory allocation</h3>
<p>Allocating a zeroed out block of memory or a set of objects (calloc)</p>
<pre><code>
var = LIBRDF_CALLOC(type, count, size)
</code></pre>
<p>Prefering when <code>count</code> = 1 this form:</p>
<pre><code>
var = LIBRDF_CALLOC(type, 1, sizeof(*var))
</code></pre>
<p>Allocating a block of memory:</p>
<pre><code>
var = LIBRDF_MALLOC(type, size)
</code></pre>
<p>Freeing memory: </p>
<pre><code>
LIBRDF_FREE(type, var)
</code></pre>
<p>The reasoning here is to make allocs mostly fit into 1 line without
too much boilerplate and duplication of types.</p>
<p>The macro names vary by library such as <code>RAPTOR_CALLOC</code> and
<code>RASQAL_CALLOC</code> for Raptor and Rasqal respectively.</p>
<h3>Documentation</h3>
<p>Public functions, types, enumerations and defines must have autodocs -
the structured comment block before the definition. This is read by
<code>gtk-doc(1)</code> to generate reference API documentation.</p>
<p>Format:</p>
<pre><code>
/**
* functionname:
* @param1: Description of first parameter
* @param2: Description of second parameter (or NULL)
* ... more params ...
*
* Short Description
*
* Long Description.
*
* Return value: return value
*/
returntype
functionname(...)
{
... body ...
}
</code></pre>
<p>The <em>Short Description</em> have several commmon forms:</p>
<ul>
<li>Constructor - creates a FOO object</li>
<li>Destructor - destroys a FOO object</li>
<li>Short description of regular function or method.</li>
<li>INTERNAL - short description</li>
</ul>
<p>The latter is used for autodocs for internal functions either as
internal documentation or for APIs that may one day be public.</p>
<p>The <em>(or NULL)</em> phrase is used for pointer parameters that may be
omitted. This is usually tested by the function as an assertion.
In some functions there are more complex conditions on which optional
parameters are allowed, these are described in the <em>Long Description</em>.</p>
<p>The long description may also include a deprecation statement such as:</p>
<pre><code>
* @Deprecated: Use new_function() with foo = BAR
</code></pre>
<p>This must be indented to the left and will be used by the
<code>gtk-doc(1)</code> document generator to provide a link to the replacement
function and usage.</p>
<h2>Commit Messages</h2>
<p>The general standard for Redland libraries using GIT is a merge
of the GIT standards format and GNU ChangeLog</p>
<pre><code>
First line summaries what commit does - this goes into the GIT short log
(function1, function2): what changed
(function3): Added, deprecating function4()
(function4): Deleted, replaced by function3()
struct foo gains field ...
struct bar loses field ...
enum blah gains new value BLAH_2 which ...
</code></pre>
<p>Use <code>name()</code> in the description for references to functions.
Make sure to do (function1, function2) NOT (function1,function2) as
it makes things easier to format later.</p>
<p>Sometimes it's short enough (good) that it all can be done in the first
line, pretty much only if it's a small change to a single function.</p>
<p>If the change is trivial or a typo and (this is <em>IMPORTANT</em>) NOT a
commit to code files, then the commit can start with '#'. This may
get filtered out of commit log message notifications and ChangeLog.</p>
<p>e.g. <code>#spelling</code> or <code>#ws</code>
the latter is whitespace changes for some reason</p>
<p>The changes will semi-automatically be added to the ChangeLog files
following the GNU style, indented and word wrapped, and adding the list
of files at the start. So the commit message above ends up looking
something like:</p>
<pre><code>
2010-08-23 User Name <user@example.org>
* dir/file1.c, dir2/file2.c: First line summaries what commit
does - this goes into the GIT short log
(function1, function2): what changed
(function3): Added, deprecating function4()
(function4): Deleted, replaced by function3()
struct foo gains field ...
struct bar loses field ...
enum blah gains new value BLAH_2 which ...
</code></pre>
<!--
Local variables:
mode: markdown
End:
-->
<hr />
<p>Copyright (C) 2010 <a href="http://www.dajobe.org/">Dave Beckett</a></p>
</body>
</html>
|