libtransmission was written in C for fifteen years, so eliminating all Cisms is nearly impossible. Modernization
patches are welcomed but it won't all happen overnight. tr_strdup() and constexpr wil exist side-by-side in the
codebase for the forseeable future.
It's so tempting to refactor all the things! Please keep modernization patches reasonably focused so that they will be
easy to review.
Prefer std:: tools over bespoke ones. For example, use std::vector
instead of tr_ptrArray. Redundant bespoke code should be removed.
Consider ripple effects before adding C++ into public headers. Will it break C code that #includes that header? If you think it might, consult with downstream projects to see if this is a problem for them.
Satisfy clang-tidy. libtransmission/.clang-tidy's list of rules should eventually be expanded to a list similar to the one in qt/.clang-tidy.
Group member functions and their parent structs
Use namespace libtransmission
Split large modules into smaller groups of files in a libtransmission/<name> subdirectories, with own
sub-namespace.
Enums replaced with new enum class syntax. Numeric #define constants replaced with C++ const/constexpr.
Memory - promote init and free functions to C++ ctors and dtors, and ensure it is only managed with new/delete
Owned memory - promote simple pointer fields owning their data to smart pointers (unique_ptr, shared_ptr, vector,
string)
Detailed Steps
Satisfy clang-tidy warnings
Change C includes to C++ wraps, example: <string.h> becomes and update calls to standard library to
use std:: namespace prefix. This clearly delineates the border between std library and transmission. Headers
must be sorted alphabetically.
Headers which are used conditionally based on some #ifdef in the code, should also have same #ifdef in the
include section.
Revisit type warnings, int vs unsigned int. Sizes and counts should use size_t type where this does not
break external API declarations. Ideally change that too.
Move and group code together.
Move member functions into structs. To minimize code churn, create function forward declarations inside structs,
and give struct_name:: prefixes to the functions.
For functions taking const pointer, add const after the function prototype: int blep() const like so.
For structs used by other modules, struct definitions should relocate to internal *-common.h header files.
Split large files into sub-modules sharing own separate sub-namespace and sitting in a subdirectory
under libtransmission/.
Some externally invoked functions must either not move OR have extern "C" adapter functions.
Enums promoted to enum class and given a type:
enum{A,B,C};
becomes
enum: int{A,B,C};// unscoped, use A, B, C
enumMyEnum:int{A,B,C};// unscoped, use A, B, C
// OR wrap into a scope -
enumstructMyEnum:int{A,B,C};// scoped, use MyEnum::A
enumclassMyEnum:int{A,B,C};// scoped, use MyEnum::A
this will make all values of enum to have that numeric type.
Numeric/bool #define constants should be replaced with C++ const/constexpr.
Memory management:
Prefer constructors and destructors vs manual construction and destruction. But when doing so must ensure that the
struct is never constructed using C malloc/free, but must use C++ new/delete.
Avoid using std::memset on a new struct. It is allowed in C, and C++ struct but will destroy virtual table on a
C++ class. Use field initializers in C++.
Owned memory:
If destructor deletes something, it means it was owned. Promote that field to owning type (vector, unique_ptr,
shared_ptr or string).