Contributing to the ETL
Thanks for considering a contribution! Here’s what you need to know before opening a pull request:
If you are thinking of adding a new feature then raise this on the GitHub Issues page for discussion as the maintainers and users of the ETL may have questions or suggestions. It is possible that the maintainer of the ETL or another contributor is already working on the same or a related feature.
Take a look through our current issues and see if anything sparks your interest!
Although the majority of the library has been written by me, I’m always open to contributions from other people. There are always a number of features and enhancements that either I’d like to see, or have been suggested by other users, but I only have a finite amount of time to give.
I accept contributions both big and small; If you have an idea for a funky non-standard container that you think would complement the library, then let us know. If you just want to add an enhancement to an existing class, tell us about that too.
This is a very friendly project and I’m not going to start shouting at you if I see issues with your idea or code. If there is a problem then we can have a dialog about what should be changed.
Feel free to argue your case.
There are always a number of issues outstanding that could usefully be taken up whole, or in part, by someone else.
Project Style
I care about code style and will flag issues in review, but I promise to be constructive about it, not aggressive. With that said, here are a few design rules I ask you to adhere to.
Public API
The style of the public API of the class should mirror that of the STL.
Class and function names
Lower case class and function names, separated by an underscore.
funky_container
do_something
Nameing convension
Use the same naming convention as the STL.
If appropriate for the class, a set of typedefs should often be present to define types such as…
type
value
value_type
size_type
pointer
const_pointer
reference
If the code is only for C++11 and above you may use the more modern using syntax.
Similarity to the STL
If a function does something similar to that in a standard class in the STL then use the same terminology.
push_back
insert_after
erase
assign
clear
size
C++ standards
If a feature is only implementable for a certain C++ standard or above, wrap the code in
#if #endif, with one of the following:-
ETL_USING_CPP11 For C++11 or above
ETL_USING_CPP14 For C++14 or above
ETL_USING_CPP17 For C++17 or above
ETL_USING_CPP20 For C++20 or above
ETL_USING_CPP23 For C++23 or above
i.e.
#if ETL_USING_CPP11
...
#endifMacros
Macros should use THIS_STYLE.
Constants
Constants should use This_Style.
Namespace
All ETL classes are to be within the etl namespace.
Private functionality
All classes private to the ETL should reside in a nested namespace prefixed with private_
namespace etl
{
namespace private_funky_container
{
struct helper
{
//…
};
}
class funky_container
{
private_funky_container::helper helper;
};
}Naming
Use descriptive names for internal variables and functions.
Comments
Use comments to summarise or explain blocks of code that may be difficult to quickly understand.
8 bit types
Avoid using int8_t or uint8_t.
Some processors such as DSPs do not support 8 bit values. Use int_least_8_t and uint_least8_t in their place.
If int8_t or uint8_t must be used then surround the code with
#if ETL_USING_8BIT_TYPES
#endif64 bit types
If int64_t or uint64_t must be used
Then surround the code with
#if ETL_USING_64BIT_TYPES
#endifBit lengths
Never assume the bit length of a type.
If the bit length is important then either use a type from stdint.h or interrogate the type for its size.
Mininmum and maximum values
Never assume the minimum or maximum values for a type.
Use etl::numberic_limits or etl::inyegral_limits to look them up.
Compile time asserts
Where ever possible, add ETL_STATIC_ASSERT to catch errors at compile time, rather than runtime.
Run time asserts
Use the ETL macros to report runtime errors.
This will ensure that the correct code is generated for the user selected error reporting method.
ETL_ASSERT(!full(), ETL_ERROR(stack_full));
Constructors
Align the initialisation of member variables in constructors as below.
class my_new_class
{
public:
my_new_class(int a_, int b_, int c_)
: a(a_)
, b(b_)
, c(c_)
{
}
};Layout
When possible, try to tabluate the initialisation of multiple variables. It’s a lot easier to read. Don’t be too strict about it, if it would result in giant amounts of whitespace.
int count = 0;
double divisor = 1.234;
etl::string<10> name = "Default";
etl::string_view view(name, begin(), name.end());
etl::intrusive_forward_list<data_link_type> quite_long_variable_name(data1, data2, data3);ETL errors
ETL errors are packaged in exception structures. Do not get confused with this terminology, it does not mean that it will always be thrown as an exception. It may just be passed as a parameter to an error handler.
class stack_exception : public exception
{
public:
stack_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
: exception(reason_, file_name_, line_number_)
{
}
};
class stack_full : public stack_exception
{
public:
stack_full(string_type file_name_, numeric_type line_number_)
: stack_exception(ETL_ERROR_TEXT("stack:full", ETL_STACK_FILE_ID"A"), file_name_, line_number_)
{
}
};Define the file id in file_error_numbers.h
#define ETL_STACK_FILE_ID "33"
Unit Tests
Every class or function that is in the library must be unit tested. Do not submit your code unless you have a full set of tests that exercise as much of the functionality as you can possibly think of. Make sure that you cover all of the corner cases.
There is a project file for VS2022 for C++14, 17, 20, 23, and bash scripts that run the tests for C++11, 14, 17, 20, 23 under Linux with GCC and Clang.
Bash Scripts
There are bash scripts to test the ETL under Linux. These scripts are run from the test directory.
run-tests.sh |
Runs the set of unit tests with various options and compilers. |
|---|---|
| Syntax | ./runtests.sh <C++ Standard> <Optimisation> <Threads> <Sanitizer> <Compiler> |
| C++ Standard | 11, 14, 17, 20, or 23 (mandatory argument) |
| Optimisation | 0, 1, 2 or 3. Default = 0 |
| Threads | Number of threads to use. Default = 4 |
| Sanitizer | s enables sanitizer checks, n disables. Default disabled |
| Compiler | gcc or clang. Default All compilers |
run-syntax-checks.sh |
Runs the set of header files through the compilers to test syntax correctness. |
|---|---|
| Syntax | ./runtests.sh <C++ Standard> <Threads> |
| C++ Standard | a, 03, 11, 14, 17, 20, or 23. a = All standards |
| Threads | Number of threads to use. Default = 4 |
| Compiler | gcc or clang. Default = All compilers |
Pull Requests
If you wish to create a pull request to the ETL repository on GitHub then create your changes in a branch that is based on master. When you think you have completed your modifications then raise a pull request.
When opening a new pull request, ensure that you include the following information.
- Is this brand new functionality, an enhancement to existing code?
- If it is a bug fix, What problem are you solving? Give an example of how to reproduce it.
- If it is a new feature or enhancement, what will be the benefit to the ETL or user of the library?
- If you are adding or modifying a feature, add new unit tests that test that feature.
- If you are fixing a bug, add a unit test that fails before the bug fix is implemented.
- Do not initiate a pull request until all of the units tests pass. See above for information on project files and test scripts.
- Branches should be based on the branch
master.
developmentcan change quite frequently, so I will rebase the your PR against it before merging. - For formatting help, you can use
clang-format, or the convenience wrappertreefmt. See also Source formatting. - Update the relevent documentation markdown file, found in
etl/docs.