Coding style¶
Cahute is made to be compatible with as much platforms as possible, adopting the lowest C standard (C89/C90) and protecting platform-specific usage behind macros as much as possible.
Formatting¶
In order to focus as much as possible on the work that matters, Cahute relies heavily on autoformatting and uncompromising sets of rules enforceable through tooling. This includes:
For C code, the use the clang-format with a set of rules described in
.clang-format
, installed as a pre-commit hook.For Python code, the use of Black.
Otherwise, the rules are not yet clearly defined, and may be as a few contributions have gone by, and the standard for Cahute shapes itself a bit more clearly.
Namespace¶
Cahute reserves both the cahute_
and CAHUTE_
prefixes for all
symbols and macros, i.e. it is recommended a library user does not use
that prefix in any of their work.
Cahute respects reserved namespaces from C and POSIX; see Open Group Base Specifications Issue 7, section 2.2.2 The Name Space for more information.
Note
This notably prevents us from using the _t
suffix, since it
is reserved by POSIX / Single UNIX Specification.
To avoid overlapping with user macros, function and macro parameters are also
defined within the Cahute namespaces, more specifically in the cahute__
and CAHUTE__
(double underscore) namespaces.
For example, a preprocessed Cahute macro and function declaration in public headers are the following:
#define CAHUTE_MY_MACRO(CAHUTE__ARG1, CAHUTE__ARG2) ...
int cahute_open_usb_link(
cahute_link *cahute__linkp,
unsigned long cahute__flags,
int cahute__bus,
int cahute__address
);
Note
The namespace mainly applies to public headers from Cahute. Within internal headers and source files, only exported symbols need to be placed within the reserved namespaces.
Exported symbols in the Cahute static library can be found using nm
:
nm -CgU libcahute.a
Compatibility¶
Cahute is designed to be more compatible than not, but to make use of compiler and platform specific tools for static analysis if possible. As such, you must use the relevant compatibility macros for your case:
Both function declarations and definitions must use the following:
Either
CAHUTE_EXTERN
, or the function is only to be used by other code in the same file,CAHUTE_LOCAL
orCAHUTE_INLINE
.Functions internal to Cahute but used cross-file must make use of
CAHUTE_EXTERN
, but be declared inlib/internals.h
instead of the public headers.CAHUTE_NNPTR
andCAHUTE_NONNULL
together, where relevant.
Function declarations only must use
CAHUTE_DEPRECATED
andCAHUTE_WUR
where relevant.
Only utilities available in C89 / C90 must be used.
For easier implementation, the following out-of-standard general utilities are available:
Portable fixed-width integer types, in the form of
cahute_u8
,cahute_u16
andcahute_u32
.Portable printf specifiers for
cahute_u8
,cahute_u16
,cahute_u32
andsize_t
.Endianness conversion utilities for both 16-bit and 32-bit integers, as
cahute_be16toh()
,cahute_le16toh()
,cahute_be32toh()
,cahute_le32toh()
,cahute_htobe16()
,cahute_htole16()
,cahute_htobe32()
,cahute_htole32()
.
Warning
When fopen()
is used, the b
flag must be used to ensure that
platforms don’t operate conversions by default:
/* WRONG. */
FILE *fp = fopen("myfile.txt", "r");
/* Correct! */
FILE *fp = fopen("myfile.txt", "rb");
This is notably useful for platforms such as Windows, that operates
conversions by default (i.e. use rt
instead of rb
by default),
except on seeking / telling, which could cause problems where the
computed file size does not match with the size of the actually read data.
Memory¶
Cahute does not use global mutable variables; its only globals are constants, i.e. read-only, and mutable “global” variables are placed in contexts, so that different users of the Cahute library in the same process do not use the same resources.
See Contexts for more information.