Coding Style
To maintain consistency within the CAM software source code a series of rules and guidelines have been created; these form the project’s coding style.
Source Code
Unicode
The source code must use the UTF-8 encoding. Comments, documentation and strings may use non-ASCII characters when required (e.g. Greek letters used for units).
License Headers
All files must begin with a license header of the following form:
Critical Application Monitoring (CAM)
SPDX-FileCopyrightText: <text>Copyright <years> Arm Limited
and/or its affiliates <[email protected]></text>
SPDX-License-Identifier: BSD-3-Clause
Where ‘<years>’ is a list of years the file received updates. Contiguous years may be written in the form of a hyphened range, example: ‘2019, 2021-2023’.
C Code Style
Clang Format
To aid in establishing a uniform style across the code-base, this project uses Clang Format. When contributing patches, care should be taken to ensure that code has been formatted according to the rules laid down in the .clang-format file, and that deviations occur only where the tool is unable to format code reasonably.
Braces
Conditional statements and iteration statements with a single line or multiple lines of code must be surrounded by braces:
if (condition) {
function_call(
long_variable_name_x,
long_variable_name_y,
long_variable_name_z);
}
This rule applies also to an if-else chain:
if (condition) {
function_call(
long_variable_name_x,
long_variable_name_y,
long_variable_name_z);
} else {
function_call_b();
}
Empty loop statements must use continue:
while (condition) {
continue;
}
Operators
When using operators like sizeof and alignof, where possible use the value-based version over the type-based version:
int counter;
sizeof(counter); /* Preferred over sizeof(int) */
Operator Precedence
Do not rely on the implicit precedence and associativity of operators. Use parentheses to make precedence and associativity explicit:
if ((a == 'a') || (x == 'x')) {
do_something();
}
Parentheses around a unary operator and its operand may be omitted:
if (!a && *b) {
do_something();
}
Header Guards
All headers must be wrapped with include guards to prevent accidental multiple
definitions of header contents. The definition name should be the upper-case
file name followed by _H
. An example for a file named cam_mm.h
follows:
#ifndef CAM_MM_H
#define CAM_MM_H
(...)
#endif /* CAM_MM_H */
Inclusion Policy
The closing endif
statement should be followed directly by a single-line
comment which replicates the full guard name. In long files this helps to
clarify what is being closed.
Macros and Constants
All macro and constant names must be written in upper-case to differentiate them from functions and non-constants.
Logical groupings of constants should be defined as enumerations with a common
prefix, so that they can be used as parameter types and in constant expressions.
Enumerations that contain a “number of elements” value must use the _COUNT
suffix, and the final enumeration value should include a comma.
enum cam_msg_a2s_id {
CAM_MSG_A2S_ID_INIT = 1,
CAM_MSG_A2S_ID_START,
CAM_MSG_A2S_ID_STOP,
CAM_MSG_A2S_ID_EVENT,
CAM_MSG_A2S_ID_COUNT,
};
void cam_process_msg_id(enum cam_msg_a2s_id id)
{
(...)
}
Symbol Naming
Function, variable, file name and type names must:
Be written in lower-case
Have compound words separated by underline characters (
_
)
Avoid using:
Camel case syntax (e.g.
criticalAppMonitor
)Hungarian notation, encoding types within names (e.g.
int iSize
)
Loop Indices
It is acceptable to use the following common placeholder names for loop indices:
i
j
k
Types
Avoid defining custom types with the typedef
keyword except for opaque
types. Names defined with typedef
must use the _t
suffix.
Initialization
When literals require explicit literal initialization, avoid implicit casts by using the proper integer literal suffix or initializer:
void *p = NULL;
unsigned int u = 0u;
float f = 0.0f;
double d = 0.0;
char c = '\0';
Array and structure initialization should use designated initializers. These allow elements to be initialized using array indices or structure field names without a fixed ordering:
uint32_t value_array[3] = {
[2] = 800,
[0] = 675,
};
struct cam_struct x = {
.name = "example",
.value = 100,
};
Doxygen Comments
libcam APIs are documented using Doxygen comments.
At a minimum:
All functions and structures must have at least a
brief
tagAll functions must document their parameters (if any) with the
param
tagInput parameters must use
param[in]
Output parameters must use
param[out]
Input/output parameters must use
param[in, out]
All functions returning a value should use the
return
and, optionally, theretval
tag to document their return value *return
should document what the type of the return value represents *retval
should document what individual return values represent
Alignment and indentation:
Documentation must also obey the 80 column limit
Multiple lines of documentation on an entry (e.g. details) must be indented using the equivalent of two 4-space based tabs from the first column (see example below)
Function documentation example:
/*!
* \brief Retrieve the library version.
*
* \details This function retrieve the current of the library.
*
* \param[out] major Pointer to the major version number.
*
* \param[out] minor Pointer to the minor version number.
*
* \retval 0 The version is retrieved with success.
* \retval -1 Failed to retrieve the library version. The returned major and
* minor are invalid.
*/
int cam_version(unsigned int *major, unsigned int *minor);
Structure documentation example:
/*!
* \brief A structure example.
*
* \details This is an example of a structure for the code style documentation.
*/
struct cam_structure {
/*!
* \brief Example field.
*/
unsigned int example;
};
Python
Python based tools must follow the PEP8 specification. This is enforced
with the pycodestyle
tool.
Python code must be linted with pylint
.
Sphinx-based Documents
Sphinx-based documents must use the following style.
Headings
The following headings style should be used:
########################
Heading 1 using overline
########################
************************
Heading 2 using overline
************************
Heading 3
=========
Heading 4
---------
Heading 5
^^^^^^^^^
Heading 6
"""""""""
Code blocks
Use the code-block
directive and specify the programming language. As
an example:
.. code-block:: python
import this
Alignment and Indentation
Documentation source must obey the 80 column limit.
The indentention must be 2-spaces.
Comments
To ensure a consistent look, the preferred style for single-line comments is to use the C89 style of paired forward-slashes and asterisks, ending with no punctuation:
/* A short, single-line comment */
Multi-line comments should follow a similar style, and always end with punctuation:
Doxygen comments follow only the second style, for consistency in the generated documentation:
Preprocessor if 0 is preferred for commenting out blocks of code where it is necessary to do so, as these can be nested (unlike multi-line comment blocks).
Prefer functions to function-like macros where possible. Avoid using the
inline
keyword, as inlining sites are better-determined by the compiler.