AviSynth+ Coding Guidelines
Whenever submitting code to the AviSynth+ codebase, the following coding conventions should be followed. Maintainers are free to reject contributions if these are wildly violated. Of course, these rules are only rules of thumb, and exceptions can be made on a case-by-case basis, but violations should be reviewed by a person other than the original author of the code in question.
- Avoid using compiler-specific language extensions.
- C++11 is allowed as long as it is correctly supported by Visual C++ 2012.
- RTTI (Run Time Type Information) should not be used.
- Exceptions should not be used. Internal APIs with exception-less variants should be preferred over older alternatives.
- Header files should only contain declarations or class templates.
- Headers must be wrapped in include guards.
- The header include guard must work across all compilers, e.g. use #ifdef instead of #pragma once.
- Headers must do what is reasonable to decrease code dependencies across source files. As such, use only the minimum necessary number of includes, and use forward declarations where appropriate.
- Multiple inheritance should not be used.
- Classes should strive to implement the RAII pattern. Once a constructor has finished execution without errors, the object should be usable until the destructor executes.
- Class methods should not mutate the object into an unusable state. If they would, they should return an error instead.
- Avoid friend classes. Look for a class hierarchy design where friends can be replaced by public interfaces without exposing too much of the internal functionality.
- Methods should represent actions and should be named accordingly.
- Methods that should not write class members (and thus do not change object state) should be marked as const.
- Output arguments of a function should be pointers, not references.
- Primitive input arguments of a function should by passed by value.
- Complex input data types (PODs, aggregates) should be passed as const references.
- All references passed as an argument should be const.
- Class pointer input arguments which were already pointers at the call site may be passed as (const) pointers.
- Methods should not span multiple pages. Keep method definitions reasonably short, breaking them up into smaller functions if necessary.
- For functions used only in a single .cpp file, prefer making them both free and static.
Types and Values
- Do not use "0" as the null-pointer constant. Use NULL or nullptr.
- Do not use signed types for variables that should never have negative values.
- Use a struct only for passive objects that carry data. Everything else is a class.
- Prefer an enum over multiple related #defines.
- Do not use global static variables.
- Choose your types to minimize casts.
- Do not use "long". It is not portable.
- Use types from standard headers where appropriate (uintptr_t, uint64_t, size_t, etc.).
- Avoid using external libraries in the core. If inevitable, the functionality requiring the external library should be implemented in a separate plugin.
- Make use of the C++ STL. E.g., prefer std::vector over arrays allocated with new, and std::string over char* to manage a string's lifetime. If you need to store an object reference in multiple objects at the same time, consider using std::shared_ptr. Etc.
- Make use of the C++ STL **correctly**. Learn the difference between a set, a map, an unordered_map, and understand when you need a list over a vector.
- You must use spaces instead of tabs for indentation.
- Prefer using 4 spaces for indentation.
- Prefer putting opening braces on new lines.
- Use CamelCase for class names.
- Use CamelCase for class-member functions.
- Use lower_case for free (non-member) functions.
- Do not use CamelCase naming for member or local variables.
- Stay consistent to yourself in your coding style.
- Use Git.
- Preferably, use GitHub.
- Commit often.
- Commit small pieces of code at a time.
- Only commit code that compiles.
- Do not mix unrelated changes in the same commit. E.g. do not commit two separate bugfixes/features as one, and commit cleanup/refactor work separately from other changes.
- Use descriptive commit messages.
- Try to issue pull requests against the latest commit of the branch you branched from. Use rebase to achieve that if necessary. Merge often from your origin to ease rebases.
- Inline ASM is forbidden. Intrinsics are preferred.
- Avoid preprocessor macros.
- Do not leave compiler warnings in your own code.
- The code should never crash. Check for possible runtime error conditions, and provide graceful error codes or error messages if something goes wrong.
- Don't forget to clean up correctly even in case of errors. Don't leak resources.
- Use asserts to check for conditions that should always be true.
- All code must be 64-bit compatible.
- If in doubt, comment rather more than less.
- It is okay to submit code that is not finished. The code must still compile though, and it must not negatively affect other (already working) functionality. You must also mark the undone parts with TODO comments explaining what must still be done.
- Don't be afraid to ask others.