Skip to content
Snippets Groups Projects
Commit 9895f372 authored by Adrien Béraud's avatar Adrien Béraud
Browse files

Update Libring coding rules

parent 7ff6fe2b
Branches
No related tags found
No related merge requests found
...@@ -19,306 +19,5 @@ daemon).** ...@@ -19,306 +19,5 @@ daemon).**
<!-- --> <!-- -->
- Rules are based on [Google C++ - Rules are defined by this clang-format file:
CodingStyle](https://google.github.io/styleguide/cppguide.html). https://git.jami.net/savoirfairelinux/ring-daemon/blob/master/.clang-format
We've modified them for this project.
This wiki is a permanent Work-In-Progress system. **So not all rules are
written yet.** That doesn't mean we don't have them yet (we == core
developer members).
- Some strongly recommended reading about modern C++:
- [ISO C++ SuperFAQ](https://isocpp.org/faq)
- [Herb Sutter GotW](https://herbsutter.com/gotw/)
------------------------------------------------------------------------
## Rules
### Language Standard
We SHALL use the **C++17 standard** syntax only.
For gnu-gcc and clang, use compiler command line option `-std=c++17` to
enforce this rule.
### Maximum Line Length
You SHOULD keep your line length under the **120 characters limit**.
This is mainly so that integrators can use split view to compare files,
and keeping the line width below 120 columns makes this easier, even on
wide screens. Configure your editing tools to this limit.
If this rule impacts negatively the readability or the validity of the
code, it can be transgressed. Here are a few valid **exceptions** to
that rule:
1. If a comment line contains an example command or a literal URL
longer than 120 characters, that line may be longer than 120
characters for ease of cut and paste.
2. A raw string literal may exceed 120 characters. Except for test
code, such literals should appear near the top of a file.
3. An \#include statement with a long path may exceed 120 columns.
### Non-ASCII Characters
Non-ASCII characters should be rare, and MUST use **UTF-8** formatting.
You SHALL NOT use the C++11 char16\_t and char32\_t character types,
since they're for non-UTF-8 text. For similar reasons you also SHALL NOT
use wchar\_t (unless you're writing code that interacts with the Windows
API, which uses wchar\_t extensively).
### Spaces vs. Tabs
In code files (i.e. .cpp or .h), you SHALL use **spaces to indent**.
One indent level is 4 (four) consecutive spaces. You should set your
editor to emit spaces when you hit the tab key and when you save your
file.
### Header multiple-inclusion guard
All header files SHALL have **an unique header guard** to prevent
multiple inclusion, using \#ifndef xxx ... \#define xxx ... \#endif form.
The format of the symbol name may be <FILE>\_H or \_<FILE>\_H\_, but you
MUST ensure its uniqueness.
We also support the pragma once form ONLY in non publicly exposed
headers files, as only GCC and clang are supported to build the daemon
core.
Example with the **foo.h file**:
```cpp
#ifndef FOO_H #define FOO_H
...
#endif // FOO_H
```
**Notice the MANDATORY comment of the ending \#endif.**
Example with **pragma version**:
```cpp
#pragma once
```
### Namespace
We're using **Named namespace**.
- All symbols that are not exposed SHALL be in ring namespace.
- All symbols that are publicly exposed SHALL be in DRing namespace.
A **single namespace** SHALL be written like this:
```cpp
namespace mynamespace {
// Follow our namespace scoped code
class Foo {
(...)
};
} // namespace mynamespace
```
+ A namespace definition block DOESN'T indent the encapsulated code.
+ The closing bracket SHALL be commented with the related namespace.
A **nested namespace** may be written like
this:
```cpp
namespace mynamespace1 { namespace mynamespace2 { namespace mynamespace3 {
// some code that belong to mynamespace1::mynamespace2::mynamespace3
} // namespace mynamespace1::mynamespace2::mynamespace3
```
+ This single-line notation is used until C++ standard adopts the form
namespace A::B::C {
If you need to express different code in multiple namespace you may use
for example the form:
```cpp
namespace mynamespace1 {
namespace mynamespace2 {
// some code that belong to mynamespace1::mynamespace2
} // namespace mynamespace1::mynamespace2
namespace mynamespace3 {
// some code that belong to mynamespace1::mynamespace3
} // namespace mynamespace1::mynamespace3
} // namespace mynamespace1
```
Namespaces wrap the entire source file after includes, gflags
definitions/declarations, and forward declarations of classes from other
namespaces.
- You SHALL NOT use a *using-directive* to make all names from a
namespace available. Particullary true for the standard
library (std::)
<!-- -->
```cpp
// Forbidden -- This pollutes the namespace.
using namespace foo;
```
- You may use a *using-declaration* anywhere in a .cpp file, and in
functions, methods or classes in .h files.
<!-- -->
```cpp
// OK in .cpp files.
// But must be in a function, method or class in .h files.
using ::foo::bar;
```
### Naming
- _General Rules_
Names SHOULD be descriptive; avoid abbreviations.
Give as descriptive a name as possible, within reason. Do not worry
about saving horizontal space as it is far more important to make your
code immediately understandable by a new reader. Do not use
abbreviations that are ambiguous or unfamiliar to readers outside your
project, and do not abbreviate by deleting letters within a word.
- _Type Names_
Type names start with a capital letter and have a capital letter for
each new word, with no underscores: MyExcitingClass, MyExcitingEnum.
- _Class Data Members_
All private data members of classes, both static and non-static, are
named like ordinary nonmember variables, but with a trailing underscore.
```cpp
class Call {
...
private:
int number_; // OK - underscore at end.
std::string peerName_; // OK.
static std::vector<Call> subCalls_; // OK.
};
```
### Casting
- You SHOULD avoid C casts, prefer C++ casts (static\_cast,
const\_cast, reinterpret\_cast)
_Rationale:_ Both reinterpret\_cast and C-style casts are
dangerous, but at least reinterpret\_cast won't remove the const
modifier
- It's RECOMMENDED to use brace initialization for conversion of POD
types like int{myFloat} instead of (int)myFloat
_Rationale:_ When refactoring code, the compiler will instantly let
you know if the cast would become dangerous.
Using brace initialization (*{}*) permits compile-time detection of
dangerous narrowing conversion, not detected with classic constructor
call (with brackets *()*).
### Static and Global Variables
Static or global variables of class type are FORBIDDEN: this is the
source of static initialization order fiasco.
Take a look to this library talking about the issue and trying to remove
them as possible:
<https://cryptopp.com/wiki/Static_Initialization_Order_Fiasco>
However, such variables are allowed if they are constexpr: they have no
dynamic initialization or destruction.
Objects with static storage duration, including global variables, static
variables, static class member variables, and function static variables,
must be Plain Old Data (POD): only ints, chars, floats, or pointers, or
arrays/structs of POD.
### Microsoft Compiler Compliance
Guidelines for compliance with Microsoft (R) C/C++ Optimizing Compiler
Version 19.00.23918
If alternative tokens for logical operators (<i>and, not, or</i> etc.)
are used, you must include <ciso686>
```cpp
// source or header file in which alternate logical operator tokens are used
#include <ciso646>
```
Initializing (nested) structures should be complete and implicit without
the use of designators
```cpp
struct A {
struct B {
int ivalue;
} child;
bool bvalue;
};
A wrong = { .child = { .ivalue = 1 }, .bvalue = true }; //error in MSVC
A right = { { 1 }, true }; //OK in MSVC
A right = { true }; //OK but will assign ivalue to true
```
## Automatic Formating
Correctly format your code using following **astyle** (versions &lt;
3.0) command:
`astyle --indent=spaces=4 --max-code-length=120 --attach-namespaces --attach-inlines --attach-extern-c --indent-switches --indent-preproc-define --indent-col1-comments --min-conditional-indent=0 --break-blocks --keep-one-line-blocks --pad-header --unpad-paren --align-pointer=type --align-reference=type --close-templates <input-files>`
With astyle >= v3.0, we recommand to add these options too:
`--pad-oper --pad-comma`
## Future
This section is related to future features related to Coding Rules
chapter.
### CPPLINT
Google has made an automatic tool to check coding rules conformance of
C++ sources. We may use it, with modifications, to help contributors to
check their code in an automatic way, before submitting it for review.
This tool is written in Python and available from (in its origin form)
here:
<http://google-styleguide.googlecode.com/svn/trunk/cpplint/cpplint.py>
The modified version for Ring is under development/testing and is
available in the tools directory as cpplint.py3.
You can see it online using our GitHub mirror:
<https://github.com/savoirfairelinux/ring-daemon/blob/master/tools/cpplint.py3>
### Helpers
Check all sources on ring-daemon project (adapt verbose level as
needed):
`find src bin -regex '.*\.\(cpp\|h\)' -a -not -regex '.*\.adaptor.h' | xargs cpplint.py --linelength=120 --filter=-build/header_guard --verbose=5 {}`
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment