Coding standard

From OdaWiki

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, not 0.
  • 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 or const 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

External Links