diff --git a/guidelines/Libring-coding-rules.md b/guidelines/Libring-coding-rules.md index 601e873cf1e6191a151305d0a489bae5df65a656..e1eea6352f64590c60cc8db6c82812a422f5c0f0 100644 --- a/guidelines/Libring-coding-rules.md +++ b/guidelines/Libring-coding-rules.md @@ -19,306 +19,5 @@ daemon).** <!-- --> -- Rules are based on [Google C++ - CodingStyle](https://google.github.io/styleguide/cppguide.html). - 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 < -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 {}` +- Rules are defined by this clang-format file: +https://git.jami.net/savoirfairelinux/ring-daemon/blob/master/.clang-format