Skip to content
Contributing to the ETL

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
...
#endif

Macros

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
#endif

64 bit types

If int64_t or uint64_t must be used Then surround the code with

#if ETL_USING_64BIT_TYPES
#endif

Bit 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.
    development can 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 wrapper treefmt. See also Source formatting.
  • Update the relevent documentation markdown file, found in etl/docs.