summaryrefslogtreecommitdiff
path: root/CODING_STYLE
diff options
context:
space:
mode:
authorCarl Worth <cworth@cworth.org>2005-06-03 14:51:57 +0000
committerCarl Worth <cworth@cworth.org>2005-06-03 14:51:57 +0000
commit36beed9bf1b3ddef42e0fb1a46035ed4a6afa4f7 (patch)
tree0521492031275c76e49feb05067a4c199bfc6098 /CODING_STYLE
parentf87fd91bcf06a1e7a9332005b5d88d6b55c82548 (diff)
Add CODING_STYLE document to standardize on some style issues.
Standardize brace handling around all else clauses according to new CODING_STYLE guidelines.
Diffstat (limited to 'CODING_STYLE')
-rw-r--r--CODING_STYLE211
1 files changed, 211 insertions, 0 deletions
diff --git a/CODING_STYLE b/CODING_STYLE
new file mode 100644
index 00000000..c2c6d4a5
--- /dev/null
+++ b/CODING_STYLE
@@ -0,0 +1,211 @@
+Cairo coding style.
+
+This document is intended to be a short description of the preferred
+coding style for the cairo source code. Good style requires good
+taste, which means this can't all be reduced to automated rules, and
+there are exceptions.
+
+We want the code to be easy to understand and maintain, and consistent
+style plays an important part in that, even if some of the specific
+details seem trivial. If nothing else, this document gives a place to
+put consistent answers for issues that would otherwise be arbitrary.
+
+Most of the guidelines here are demonstrated by examples, (which means
+this document is quicker to read than it might appear given its
+length). Most of the examples are positive examples that you should
+imitate. The few negative examples are clearly marked with a comment
+of /* Yuck! */. Please don't submit code to cairo that looks like any
+of these.
+
+Indentation
+-----------
+Each new level is indented 4 more spaces than the previous level:
+
+ if (condition)
+ do_something ();
+
+Spaces or tabs (or a combination) can be used in indentation, but tabs
+must always be interpreted as 8 spaces. Code using single tabs for all
+indentation (expecting people to interpret tabs as 4 spaces) will not
+be accepted in cairo.
+
+The rationale here is that tabs are used in the code for lining things
+up other than indentation, (see the Whitespace section below), and
+changing the interpretation of tab from 8 characters will break this.
+
+Braces
+------
+Most of the code in cairo uses bracing in the style of K&R:
+
+ if (condition) {
+ do_this ();
+ do_that ();
+ } else {
+ do_the_other ();
+ }
+
+but some of the code uses an alternate style:
+
+ if (condition)
+ {
+ do_this ();
+ do_that ();
+ }
+ else
+ {
+ do_the_other ();
+ }
+
+and that seems just fine. We won't lay down any strict rule on this
+point, (though there should be some local). If you came here hoping to
+find some guidance, then use the first form above.
+
+If all of the substatements of an if statement are single statements,
+the optional braces should not usually appear:
+
+ if (condition)
+ do_this ();
+ else
+ do_that ();
+
+But the braces are mandatory when mixing single statement and compund
+statements in the various clauses. For example, do not do this:
+
+ if (condition) {
+ do_this ();
+ do_that ();
+ } else /* Yuck! */
+ do_the_other ();
+
+And of course, there are exceptions for when the code just looks
+better with the braces:
+
+ if (condition) {
+ /* Note that we have to be careful here. */
+ do_something_dangerous (with_care);
+ }
+
+ if (condition &&
+ other_condition &&
+ yet_another)
+ {
+ do_something ();
+ }
+
+And note that this last example also shows a situtation in which the
+opening brace really needs to be on its own line. The following looks awful:
+
+ if (condition &&
+ other_condition &&
+ yet_another) { /* Yuck! */
+ do_something ();
+ }
+
+As we said above, legible code that is easy to understand and maintain
+is the goal, not adherence to strict rules.
+
+Whitespace
+----------
+Separate logically distinct chunks with a single newline. This
+obviously applies between functions, but also applies within a
+function or block and can even be used to good effect within a
+structure definition:
+
+ struct _cairo_gstate {
+ cairo_operator_t operator;
+
+ double tolerance;
+
+ /* stroke style */
+ double line_width;
+ cairo_line_cap_t line_cap;
+ cairo_line_join_t line_join;
+ double miter_limit;
+
+ cairo_fill_rule_t fill_rule;
+
+ double *dash;
+ int num_dashes;
+ double dash_offset;
+
+ ...
+ }
+
+Use a single space before a left parenthesis, except where the
+standard will not allow it, (eg. when defining a parameterized macro).
+
+Don't eliminate whitespace just because things would still fit on one
+line. This breaks the expected visual structure of the code making it
+much harder to read and understand:
+
+ if (condition) foo (); else bar (); /* Yuck! */
+
+As a special case of the bracing and whitespace guidelines, function
+definitions should always take the following form:
+
+ void
+ my_function (argument)
+ {
+ do_my_things ();
+ }
+
+And function prototypes should similarly have the return type (and
+associated specifiers and qualifiers) on a line above the function, so
+that the function name is flush left.
+
+Break up long line (> ~80 characters) and use whitespace to align
+things nicely. For example the arguments in a long list to a function call should all be aligned with each other:
+
+ align_function_arguments (argument_the_first,
+ argument_the_second,
+ argument_the_third);
+
+And as a special rule, in a function prototype, (as well as in the
+definition), whitespace should be inserted between the parameter types
+and names so that the names are aligned:
+
+ void
+ align_parameter_names_in_prototypes (const char *char_star_arg,
+ int int_arg,
+ double *double_star_arg,
+ double duble_arg);
+
+Note that parameters with a * prefix are aligned one character to the
+left so that the actual names are aligned.
+
+Managing nested blocks
+----------------------
+Long blocks that are deeply nested make the code very hard to
+read. Fortunately such blocks often indicate logically distinct chunks
+of functionality that are begging to be split into their own
+functions. Please listen to the blocks when they beg.
+
+In other cases, gratuitous nesting comes about because the primary
+functionality gets buried in a nested block rather than living at the
+primary level where it belongs. Consider the following:
+
+ foo = malloc (sizeof (foo_t));
+ if (foo) { /* Yuck! */
+ ...
+ /* lots of code to initialize foo */
+ ...
+ return SUCCESS;
+ }
+ return FAILURE;
+
+This kind of gratuitous nesting can be avoided by following a pattern
+of handling exceptional cases early and returning:
+
+ foo = malloc (sizeof (foo_t));
+ if (foo == NULL)
+ return FAILURE;
+
+ ...
+ /* lots of code to initialize foo */
+ ...
+ return SUCCESS;
+
+The return statement is often the best thing to use in a pattern like
+this. If it's not available due to additional nesting above which
+require some cleanup after the current block, then consider splitting
+the current block into a new function before using goto.