|
Packit |
324a5c |
Cairo coding style.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
This document is intended to be a short description of the preferred
|
|
Packit |
324a5c |
coding style for the cairo source code. Good style requires good
|
|
Packit |
324a5c |
taste, which means this can't all be reduced to automated rules, and
|
|
Packit |
324a5c |
there are exceptions.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
We want the code to be easy to understand and maintain, and consistent
|
|
Packit |
324a5c |
style plays an important part in that, even if some of the specific
|
|
Packit |
324a5c |
details seem trivial. If nothing else, this document gives a place to
|
|
Packit |
324a5c |
put consistent answers for issues that would otherwise be arbitrary.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Most of the guidelines here are demonstrated by examples, (which means
|
|
Packit |
324a5c |
this document is quicker to read than it might appear given its
|
|
Packit |
324a5c |
length). Most of the examples are positive examples that you should
|
|
Packit |
324a5c |
imitate. The few negative examples are clearly marked with a comment
|
|
Packit |
324a5c |
of /* Yuck! */. Please don't submit code to cairo that looks like any
|
|
Packit |
324a5c |
of these.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Indentation
|
|
Packit |
324a5c |
-----------
|
|
Packit |
324a5c |
Each new level is indented 4 more spaces than the previous level:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
if (condition)
|
|
Packit |
324a5c |
do_something ();
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
This may be achieved with space characters or a combination of tab
|
|
Packit |
324a5c |
characters and space characters. It may not be achieved with tab
|
|
Packit |
324a5c |
characters exclusively (see below).
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Tab characters
|
|
Packit |
324a5c |
--------------
|
|
Packit |
324a5c |
The tab character must always be interpreted according to its
|
|
Packit |
324a5c |
traditional meaning:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Advance to the next column which is a multiple of 8.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
With this definition, even levels of indentation can be achieved with
|
|
Packit |
324a5c |
a sequence of tab characters, while odd levels of indentation may
|
|
Packit |
324a5c |
begin with a sequence of tab character but must end with 4 space
|
|
Packit |
324a5c |
characters.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Some programmers have been misled by certain text editors into
|
|
Packit |
324a5c |
thinking that 4-space indentation can be achieved with tab characters
|
|
Packit |
324a5c |
exclusively by changing the meaning of tab character to be "advance to
|
|
Packit |
324a5c |
the next column which is a multiple of 4". Code formatted in this way,
|
|
Packit |
324a5c |
making an assumption of a fictitious 4-character-tab will not be
|
|
Packit |
324a5c |
accepted into cairo.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
The rationale here is that tabs are used in the code for lining things
|
|
Packit |
324a5c |
up other than indentation, (see the Whitespace section below), and
|
|
Packit |
324a5c |
changing the interpretation of tab from its traditional meaning will
|
|
Packit |
324a5c |
break this alignment.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Braces
|
|
Packit |
324a5c |
------
|
|
Packit |
324a5c |
Most of the code in cairo uses bracing in the style of K&R:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
if (condition) {
|
|
Packit |
324a5c |
do_this ();
|
|
Packit |
324a5c |
do_that ();
|
|
Packit |
324a5c |
} else {
|
|
Packit |
324a5c |
do_the_other ();
|
|
Packit |
324a5c |
}
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
but some of the code uses an alternate style:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
if (condition)
|
|
Packit |
324a5c |
{
|
|
Packit |
324a5c |
do_this ();
|
|
Packit |
324a5c |
do_that ();
|
|
Packit |
324a5c |
}
|
|
Packit |
324a5c |
else
|
|
Packit |
324a5c |
{
|
|
Packit |
324a5c |
do_the_other ();
|
|
Packit |
324a5c |
}
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
and that seems just fine. We won't lay down any strict rule on this
|
|
Packit |
324a5c |
point, (though there should be some local consistency). If you came
|
|
Packit |
324a5c |
here hoping to find some guidance, then use the first form above.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
If all of the substatements of an if statement are single statements,
|
|
Packit |
324a5c |
the optional braces should not usually appear:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
if (condition)
|
|
Packit |
324a5c |
do_this ();
|
|
Packit |
324a5c |
else
|
|
Packit |
324a5c |
do_that ();
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
But the braces are mandatory when mixing single statement and compound
|
|
Packit |
324a5c |
statements in the various clauses. For example, do not do this:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
if (condition) {
|
|
Packit |
324a5c |
do_this ();
|
|
Packit |
324a5c |
do_that ();
|
|
Packit |
324a5c |
} else /* Yuck! */
|
|
Packit |
324a5c |
do_the_other ();
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
And of course, there are exceptions for when the code just looks
|
|
Packit |
324a5c |
better with the braces:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
if (condition) {
|
|
Packit |
324a5c |
/* Note that we have to be careful here. */
|
|
Packit |
324a5c |
do_something_dangerous (with_care);
|
|
Packit |
324a5c |
}
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
if (condition &&
|
|
Packit |
324a5c |
other_condition &&
|
|
Packit |
324a5c |
yet_another)
|
|
Packit |
324a5c |
{
|
|
Packit |
324a5c |
do_something ();
|
|
Packit |
324a5c |
}
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
And note that this last example also shows a situation in which the
|
|
Packit |
324a5c |
opening brace really needs to be on its own line. The following looks awful:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
if (condition &&
|
|
Packit |
324a5c |
other_condition &&
|
|
Packit |
324a5c |
yet_another) { /* Yuck! */
|
|
Packit |
324a5c |
do_something ();
|
|
Packit |
324a5c |
}
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
As we said above, legible code that is easy to understand and maintain
|
|
Packit |
324a5c |
is the goal, not adherence to strict rules.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Whitespace
|
|
Packit |
324a5c |
----------
|
|
Packit |
324a5c |
Separate logically distinct chunks with a single newline. This
|
|
Packit |
324a5c |
obviously applies between functions, but also applies within a
|
|
Packit |
324a5c |
function or block and can even be used to good effect within a
|
|
Packit |
324a5c |
structure definition:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
struct _cairo_gstate {
|
|
Packit |
324a5c |
cairo_operator_t op;
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
double tolerance;
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
/* stroke style */
|
|
Packit |
324a5c |
double line_width;
|
|
Packit |
324a5c |
cairo_line_cap_t line_cap;
|
|
Packit |
324a5c |
cairo_line_join_t line_join;
|
|
Packit |
324a5c |
double miter_limit;
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
cairo_fill_rule_t fill_rule;
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
double *dash;
|
|
Packit |
324a5c |
int num_dashes;
|
|
Packit |
324a5c |
double dash_offset;
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
...
|
|
Packit |
324a5c |
}
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Use a single space before a left parenthesis, except where the
|
|
Packit |
324a5c |
standard will not allow it, (eg. when defining a parameterized macro).
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Don't eliminate newlines just because things would still fit on one
|
|
Packit |
324a5c |
line. This breaks the expected visual structure of the code making it
|
|
Packit |
324a5c |
much harder to read and understand:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
if (condition) foo (); else bar (); /* Yuck! */
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Do eliminate trailing whitespace (space or tab characters) on any
|
|
Packit |
324a5c |
line. Also, avoid putting initial or final blank lines into any file,
|
|
Packit |
324a5c |
and never use multiple blank lines instead of a single blank line.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Do enable the default git pre-commit hook that detect trailing
|
|
Packit |
324a5c |
whitespace for you and help you to avoid corrupting cairo's tree with
|
|
Packit |
324a5c |
it. Do that as follows:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
chmod a+x .git/hooks/pre-commit
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
You might also find the git-stripspace utility helpful which acts as a
|
|
Packit |
324a5c |
filter to remove trailing whitespace as well as initial, final, and
|
|
Packit |
324a5c |
duplicate blank lines.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
As a special case of the bracing and whitespace guidelines, function
|
|
Packit |
324a5c |
definitions should always take the following form:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
void
|
|
Packit |
324a5c |
my_function (argument)
|
|
Packit |
324a5c |
{
|
|
Packit |
324a5c |
do_my_things ();
|
|
Packit |
324a5c |
}
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
And function prototypes should similarly have the return type (and
|
|
Packit |
324a5c |
associated specifiers and qualifiers) on a line above the function, so
|
|
Packit |
324a5c |
that the function name is flush left.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Break up long lines (> ~80 characters) and use whitespace to align
|
|
Packit |
324a5c |
things nicely. For example the arguments in a long list to a function
|
|
Packit |
324a5c |
call should all be aligned with each other:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
align_function_arguments (argument_the_first,
|
|
Packit |
324a5c |
argument_the_second,
|
|
Packit |
324a5c |
argument_the_third);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
And as a special rule, in a function prototype, (as well as in the
|
|
Packit |
324a5c |
definition), whitespace should be inserted between the parameter types
|
|
Packit |
324a5c |
and names so that the names are aligned:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
void
|
|
Packit |
324a5c |
align_parameter_names_in_prototypes (const char *char_star_arg,
|
|
Packit |
324a5c |
int int_arg,
|
|
Packit |
324a5c |
double *double_star_arg,
|
|
Packit |
324a5c |
double double_arg);
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Note that parameters with a * prefix are aligned one character to the
|
|
Packit |
324a5c |
left so that the actual names are aligned.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Managing nested blocks
|
|
Packit |
324a5c |
----------------------
|
|
Packit |
324a5c |
Long blocks that are deeply nested make the code very hard to
|
|
Packit |
324a5c |
read. Fortunately such blocks often indicate logically distinct chunks
|
|
Packit |
324a5c |
of functionality that are begging to be split into their own
|
|
Packit |
324a5c |
functions. Please listen to the blocks when they beg.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
In other cases, gratuitous nesting comes about because the primary
|
|
Packit |
324a5c |
functionality gets buried in a nested block rather than living at the
|
|
Packit |
324a5c |
primary level where it belongs. Consider the following:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
foo = malloc (sizeof (foo_t));
|
|
Packit |
324a5c |
if (foo) { /* Yuck! */
|
|
Packit |
324a5c |
...
|
|
Packit |
324a5c |
/* lots of code to initialize foo */
|
|
Packit |
324a5c |
...
|
|
Packit |
324a5c |
return SUCCESS;
|
|
Packit |
324a5c |
}
|
|
Packit |
324a5c |
return FAILURE;
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
This kind of gratuitous nesting can be avoided by following a pattern
|
|
Packit |
324a5c |
of handling exceptional cases early and returning:
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
foo = malloc (sizeof (foo_t));
|
|
Packit |
324a5c |
if (foo == NULL)
|
|
Packit |
324a5c |
return FAILURE;
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
...
|
|
Packit |
324a5c |
/* lots of code to initialize foo */
|
|
Packit |
324a5c |
...
|
|
Packit |
324a5c |
return SUCCESS;
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
The return statement is often the best thing to use in a pattern like
|
|
Packit |
324a5c |
this. If it's not available due to additional nesting above which
|
|
Packit |
324a5c |
require some cleanup after the current block, then consider splitting
|
|
Packit |
324a5c |
the current block into a new function before using goto.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Memory allocation
|
|
Packit |
324a5c |
-----------------
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Because much of cairo's data consists of dynamically allocated arrays,
|
|
Packit |
324a5c |
it's very easy to introduce integer overflow issues whenever malloc()
|
|
Packit |
324a5c |
is called. Use the _cairo_malloc2(), _cairo_malloc3(), and
|
|
Packit |
324a5c |
_cairo_malloc2_add1 macros to avoid these cases; these macros check
|
|
Packit |
324a5c |
for overflow and will return NULL in that case.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
malloc (n * size) => _cairo_malloc_ab (n, size)
|
|
Packit |
324a5c |
e.g. malloc (num_elts * sizeof(some_type)) =>
|
|
Packit |
324a5c |
_cairo_malloc2 (num_elts, sizeof(some_type))
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
malloc (a * b * size) => _cairo_malloc_abc (a, b, size)
|
|
Packit |
324a5c |
e.g. malloc (width * height * 4) =>
|
|
Packit |
324a5c |
_cairo_malloc3 (width, height, 4)
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
malloc (n * size + k) => _cairo_malloc_ab_plus_c (n, size, k)
|
|
Packit |
324a5c |
e.g. malloc (num * sizeof(entry) + sizeof(header)) =>
|
|
Packit |
324a5c |
_cairo_malloc2k (num, sizeof(entry), sizeof(header))
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
In general, be wary of performing any arithmetic operations in an
|
|
Packit |
324a5c |
argument to malloc. You should explicitly check for integer overflow
|
|
Packit |
324a5c |
yourself in any more complex situations.
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Mode lines
|
|
Packit |
324a5c |
----------
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
So given the rules above, what is the best way to simplify one's life as
|
|
Packit |
324a5c |
a code monkey? Get your editor to do most of the tedious work of
|
|
Packit |
324a5c |
beautifying your code!
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
As a reward for reading this far, here are some mode lines for the more
|
|
Packit |
324a5c |
popular editors:
|
|
Packit |
324a5c |
/*
|
|
Packit |
324a5c |
* vim:sw=4:sts=4:ts=8:tw=78:fo=tcroq:cindent:cino=\:0,(0
|
|
Packit |
324a5c |
* vim:isk=a-z,A-Z,48-57,_,.,-,>
|
|
Packit |
324a5c |
*/
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
TODO
|
|
Packit |
324a5c |
----
|
|
Packit |
324a5c |
|
|
Packit |
324a5c |
Write rules for common editors to use this style. Also cleanup/unify
|
|
Packit |
324a5c |
the modelines in the source files.
|