Difference between revisions of "Coding standard"
(→See Also) |
(→General) |
||
(10 intermediate revisions by 3 users not shown) | |||
Line 4: | Line 4: | ||
==Requirements== | ==Requirements== | ||
− | |||
− | |||
* Make logical changes in separate patches | * Make logical changes in separate patches | ||
+ | * Minimise the number of changes in each patch | ||
+ | * Provide an off switch for every new feature | ||
+ | * Do not submit things you cannot test (e.g. code for alternative platforms) | ||
==Code guidelines== | ==Code guidelines== | ||
+ | === General === | ||
+ | Things you should definitely do in your code: | ||
+ | * Include a GPL header at the top of any new files. | ||
+ | * Write code that is clear and avoids being too "tricky". | ||
+ | * Write code that is defensive and secure, don't make assumptions about inputs. | ||
+ | * Write comments that are descriptive and are of reasonable size, without being overly verbose. | ||
+ | * Maintain traditional naming conventions, for consistency. | ||
+ | * Use <code>NULL</code> for null pointers, not <code>0</code>. | ||
+ | * Add a [[test]] for every change (or an explanation of why this is impossible). | ||
Things you should definitely AVOID in your code: | Things you should definitely AVOID in your code: | ||
− | * Precompiler macros | + | * Changing code that already works. |
− | * Global variables | + | * Precompiler macros. |
− | * Variants (tagged unions) | + | * Global variables; they can create problems elsewhere in code. |
− | * Magic numbers | + | * Variants (tagged unions); they can present a performance problem. |
− | * Hungarian notation | + | * Passing non-trivial data structures by value; pass them by <code>const</code> reference instead. |
− | * C style strings | + | * Magic numbers; use <code>#define</code> or <code>const</code> in your code for fixed numbers, at the top of files. |
− | * goto | + | * Hungarian notation such as <code>intVarname</code>; it's just plan evil. |
+ | * C-style <code>char*</code> strings; replace them with C++ [http://en.cppreference.com/w/cpp/string/basic_string std::string] where it is safe to do so. | ||
+ | * C-style casts like <code>(int)</code>; use [http://en.cppreference.com/w/cpp/language/static_cast static_cast], [http://en.cppreference.com/w/cpp/language/const_cast const_cast] or [http://en.cppreference.com/w/cpp/language/reinterpret_cast reinterpret_cast] instead. | ||
+ | * <code>goto</code>. | ||
− | == | + | === Style Guidelines === |
+ | * Set your editor to use Unix line-endings (LF), not Windows (CRLF). | ||
+ | * Use tabs for indentation and spaces for alignment [http://www.emacswiki.org/SmartTabs like so]. | ||
+ | ** If this is done correctly, it does not matter what tab-width you use. | ||
+ | * Use [http://en.wikipedia.org/wiki/Indent_style#Allman_style Allman] brace style: opening and closing braces go on their own line. | ||
+ | * Use of braceless blocks is allowed. | ||
+ | * Try to limit functions to a maximum size (like the amount that would fit on a monitor with a reasonable screen resolution). | ||
+ | * Set your editor to strip trailing whitespace on save. | ||
− | + | === File Operations === | |
− | + | When using file i/o based functions, such as fopen() etc or filename string functions, there are some that are not provided, ie retrieving the length of a file, checking if a file exists or not. | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | Thankfully, Odamex provides some internal functions for doing such. Be sure to check out '''m_fileio.h''' before writing your own, it may have already been implemented! If it isn't, write us a patch and send it in. | |
− | + | ||
− | + | ||
− | + | ||
+ | Some of the useful functions included are: | ||
+ | * SDWORD M_FileLength(FILE *) - Returns the length of an open file handle | ||
+ | Filename operations: | ||
+ | * BOOL M_FileExists(std::string Filename) - Checks if a file exists or not | ||
+ | * BOOL M_AppendExtension(std::string &Filename, std::string Extension, bool If_Needed = true) - Add an extension on to the end of a filename, If_Needed detects if Extension is in Filename, if it isn't, it is added | ||
+ | * void M_ExtractFilePath(std::string Filename, std::string &Destination) - Returns the path of a filename in Destination | ||
+ | * BOOL M_ExtractFileExtension(std::string Filename, std::string &Destination) - Returns the extension of Filename in Destination | ||
+ | * void M_ExtractFileBase(std::string Filename, std::string &Destination) - Returns the base name of Filename in Destination | ||
+ | * void M_ExtractFileName(std::string Filename, std::string &Destination) - Returns the complete filename of Filename in Destination | ||
+ | |||
+ | Others include: | ||
+ | * BOOL M_WriteFile(std::string Filename, void *Buffer, QWORD Length) - Creates/overwrites a file and writes a block of data to it. | ||
+ | * QWORD M_ReadFile(std::string Filename, BYTE **Buffer) - Allocates a buffer using Z_Malloc and reads the data into it from a file, lifetime is PU_STATIC. | ||
+ | |||
+ | === Memory Management === | ||
+ | If you need to use malloc(), calloc(), realloc(), free() functions. Use the '''macros''' located in '''m_alloc.h''', these are provided because they are much better when it comes to debugging code and such: | ||
+ | |||
+ | * M_Malloc(size_t Size) | ||
+ | * M_Calloc(size_t Items, size_t Size) | ||
+ | * M_Realloc(void *Pointer, size_t Size) | ||
+ | * M_Free(uintptr_t &Reference) | ||
+ | |||
+ | A list of features these functions offer: | ||
+ | |||
+ | * The Size value can NEVER be 0, this prevents platform-specific behaviour. | ||
+ | * M_Free uses a reference instead of a pointer, it still does the same as normal free(), but will NULL the address on return. | ||
+ | * They will abort the program if their operation fails. | ||
+ | |||
+ | === Z_Zone Memory Management === | ||
+ | * Be aware that the all Z_Zone allocated memory is freed when the WAD changes | ||
==External Links== | ==External Links== | ||
* [http://www.jwz.org/doc/tabs-vs-spaces.html tabs-vs-spaces] | * [http://www.jwz.org/doc/tabs-vs-spaces.html tabs-vs-spaces] |
Latest revision as of 05:14, 4 July 2012
Contents
Overview
Odamex relies on a coding standard to ensure continuity, this reduces bugs and provides easy readability of the code.
Requirements
- Make logical changes in separate patches
- Minimise the number of changes in each patch
- Provide an off switch for every new feature
- Do not submit things you cannot test (e.g. code for alternative platforms)
Code guidelines
General
Things you should definitely do in your code:
- Include a GPL header at the top of any new files.
- Write code that is clear and avoids being too "tricky".
- Write code that is defensive and secure, don't make assumptions about inputs.
- Write comments that are descriptive and are of reasonable size, without being overly verbose.
- Maintain traditional naming conventions, for consistency.
- Use
NULL
for null pointers, not0
. - Add a test for every change (or an explanation of why this is impossible).
Things you should definitely AVOID in your code:
- Changing code that already works.
- Precompiler macros.
- Global variables; they can create problems elsewhere in code.
- Variants (tagged unions); they can present a performance problem.
- Passing non-trivial data structures by value; pass them by
const
reference instead. - Magic numbers; use
#define
orconst
in your code for fixed numbers, at the top of files. - Hungarian notation such as
intVarname
; it's just plan evil. - C-style
char*
strings; replace them with C++ std::string where it is safe to do so. - C-style casts like
(int)
; use static_cast, const_cast or reinterpret_cast instead. -
goto
.
Style Guidelines
- Set your editor to use Unix line-endings (LF), not Windows (CRLF).
- Use tabs for indentation and spaces for alignment like so.
- If this is done correctly, it does not matter what tab-width you use.
- Use Allman brace style: opening and closing braces go on their own line.
- Use of braceless blocks is allowed.
- Try to limit functions to a maximum size (like the amount that would fit on a monitor with a reasonable screen resolution).
- Set your editor to strip trailing whitespace on save.
File Operations
When using file i/o based functions, such as fopen() etc or filename string functions, there are some that are not provided, ie retrieving the length of a file, checking if a file exists or not.
Thankfully, Odamex provides some internal functions for doing such. Be sure to check out m_fileio.h before writing your own, it may have already been implemented! If it isn't, write us a patch and send it in.
Some of the useful functions included are:
- SDWORD M_FileLength(FILE *) - Returns the length of an open file handle
Filename operations:
- BOOL M_FileExists(std::string Filename) - Checks if a file exists or not
- BOOL M_AppendExtension(std::string &Filename, std::string Extension, bool If_Needed = true) - Add an extension on to the end of a filename, If_Needed detects if Extension is in Filename, if it isn't, it is added
- void M_ExtractFilePath(std::string Filename, std::string &Destination) - Returns the path of a filename in Destination
- BOOL M_ExtractFileExtension(std::string Filename, std::string &Destination) - Returns the extension of Filename in Destination
- void M_ExtractFileBase(std::string Filename, std::string &Destination) - Returns the base name of Filename in Destination
- void M_ExtractFileName(std::string Filename, std::string &Destination) - Returns the complete filename of Filename in Destination
Others include:
- BOOL M_WriteFile(std::string Filename, void *Buffer, QWORD Length) - Creates/overwrites a file and writes a block of data to it.
- QWORD M_ReadFile(std::string Filename, BYTE **Buffer) - Allocates a buffer using Z_Malloc and reads the data into it from a file, lifetime is PU_STATIC.
Memory Management
If you need to use malloc(), calloc(), realloc(), free() functions. Use the macros located in m_alloc.h, these are provided because they are much better when it comes to debugging code and such:
- M_Malloc(size_t Size)
- M_Calloc(size_t Items, size_t Size)
- M_Realloc(void *Pointer, size_t Size)
- M_Free(uintptr_t &Reference)
A list of features these functions offer:
- The Size value can NEVER be 0, this prevents platform-specific behaviour.
- M_Free uses a reference instead of a pointer, it still does the same as normal free(), but will NULL the address on return.
- They will abort the program if their operation fails.
Z_Zone Memory Management
- Be aware that the all Z_Zone allocated memory is freed when the WAD changes