Skip to content

Style Guide

Jonathan Hoffstadt edited this page Apr 12, 2024 · 1 revision

Table of Contents

General Variables Structs Enums Functions
Macros Defines Header Files C Files

General

Guidelines:

  1. meaningful names shall be used for variables, constants, and functions
  2. variables shall NOT be declared on the same line
  3. opening braces should be on a new line unless the entire scope is on the same line
  4. binary operators shall be surrounded by spaces(e.g., x = 3 + 5)
  5. one space shall be left after commas
  6. global variables should be avoided where they are unnecessary
  7. code shall NOT be split into functions unnecessarily
  8. indentation should use 4 spaces
  9. heap allocation should be minimized
  10. tertiary operators shall NOT be nested
  11. comments shall begin with "//"

Variables

Guidelines:

  1. variables shall use meaningful names
  2. variables shall follow the following naming convention:
// scalar
int           iVariable;
uint32_t      uVariable;
uint64_t      ulVariable;
size_t        szVariable;
bool          bVaribale;

// floating point
float         fVariable;
double        dVariable;

// characters
char          cVariable;
unsigned char ucVariable;

// enums & typedefs
plSomeEnum    tVariable;
plSomeStruct  tVariable;

// pointers
int*          piVariable;
uint64_t*     pulVariable;
plSomeEnum*   ptVariable;
       // ... //
char*         pcVariable;
void*         pvVariable;

// arrays
int           aiVariable[16];
uint64_t      aulVariable[16];
plSomeEnum    atVariable[16];
      // ... //
char          acVariable[16];
void          avVariable[16];

// stretchy buffers
int*          sbiVariable;
uint64_t*     sbulVariable;
plSomeEnum*   sbtVariable;
    // ... //
char*         sbcVariable;
void*         sbvVariable;

// globals
int           giVariable;
char*         gpcVariable;

Structs

Guidelines:

  1. struct names shall use camel case
  2. struct names shall be prefixed with "pl"
  3. structs should always be typedef'd
  4. structs when containing many members, should have members be grouped into sections
  5. struct member names should be aligned with other members in their section
  6. struct private/internal members shall be prefixed with an underscore and placed in the last section labeled "// [INTERNAL]"
  7. public structs should be forward declared
  8. structure tags shall match the structure name with a prefixed underscore
  9. structures should be passed by pointer unless the structure is small

Examples:

// forward declarartion
typedef struct _plPerson plPerson;

// definition
typedef struct _plPerson
{
    int         iAge;
    const char* pcName;

    // favorites & misc
    float fFavoriteFloat;
    int   iAnEvenNumber;

    // [INTERNAL]
    float _fHotness; // 0.0f...10.0f
} plPerson;

Enums

Guidelines:

  1. enum names shall use camel case
  2. enum names shall be prefixed with "pl"
  3. enum names shall be appended with an underscore
  4. enums shall never be used as "types" directly
  5. enums shall be forward declared using "typedef int plSomeEnumName;"

Examples:

// forward declaration
typedef int plChannelType;

// definition
enum plChannelType_
{
    PL_CHANNEL_TYPE_DEFAULT,
    PL_CHANNEL_TYPE_CONSOLE,
    PL_CHANNEL_TYPE_BUFFER
};

// variable
plChannelType tMyChanelType = PL_CHANNEL_TYPE_CONSOLE;

Functions

Guidelines:

  1. function names shall use snake_case
  2. function names shall be prefixed with "pl"
  3. private/internal functions shall have an additional underscore after the "pl" prefix
  4. function declarations should be on a single line
  5. most function definitions should start the function signature on a new line
  6. short and simple functions should be inlined and a single line
  7. function input arguments shall appear before out arguments

Examples:

// public functions (declarations)
int  pl_add_numbers(int iA, int iB);
bool pl_is_button_hovered();

// private/internal functions (declarations)
static float  pl__find_average(float fA, float fB);
static void   pl__fill_buffer (char* pcBuffer, size_t szSize);

// simple functions
static inline pl__add_numbers(int iA, int iB) { return iA > iB ? iA : iB; }

// definitions

int
pl_add_numbers(int iA, int iB)
{
    return iA + iB;
}

static float
pl__find_average(float fA, float fB)
{
    return (fA + fB) / 2.0f; 
}

Macros

Guidelines:

  1. macros should be uppercase with an underscore between words
  2. macros should be prefixed with "PL"
  3. macro arguments shall be surrounded by parenthesis
  4. new macros shall be created sparingly
  5. macros used to "compile out" functions should follow the function naming conventions (e.g., logging, profiling)

Examples:

// Guidelines [1][2][3]
#define PL_GET_MAX(x, y) (x) > (y) ? (x) : (y)

// Guideline [5]
#define pl_initialize_profile_context(tPContext) pl__initialize_profile_context((tPContext))

Preprocessor Defines

Guidelines:

  1. preprocessor defines shall be uppercase with an underscore between words
  2. preprocessor defines shall be prefixed with "PL"

Examples:

#define PL_MAX_GRENADES 1024

Header Files

Guidelines:

  1. header file names shall be camel case
  2. header file names should be short and concise.
  3. header file names shall be prefixed with "pl_"
  4. header file names shall be appended with the following for platform dependent headers:
    1. "_win32" for Windows specifics
    2. "_linux" for Linux specifics
    3. "_macos" for MacOs specifics
    4. "_vulkan" for Vulkan specifics
    5. "_metal" for Metal specifics
  5. header files should only include standard headers
  6. header files should be split into sections with sections denoted as:
//-----------------------------------------------------------------------------
// [SECTION] my section
//-----------------------------------------------------------------------------
  1. header files should begin with the following:
/*
   <header file name>, v0.1 (WIP)
       * brief description or notes
*/

/*
Index of this file:
// [SECTION] documentation
// [SECTION] includes
// [SECTION] defines
// [SECTION] forward declarations & basic types
// [SECTION] public api
// [SECTION] enums
// [SECTION] structs
*/

C Files

Guidelines:

  1. c file names shall be camel case
  2. c file names should be short and concise.
  3. c file names shall be prefixed with "pl_"
  4. c file names shall be appended with the following for platform dependent c files:
    1. "_win32" for Windows specifics
    2. "_linux" for Linux specifics
    3. "_macos" for MacOs specifics
    4. "_vulkan" for Vulkan specifics
    5. "_metal" for Metal specifics
  5. c files should be split into sections with sections denoted as:
//-----------------------------------------------------------------------------
// [SECTION] my section
//-----------------------------------------------------------------------------
  1. c files should begin with the following:
/*
   <c file name>, v0.1 (WIP)
       * brief description or notes
*/

/*
Index of this file:
// [SECTION] internal documentation
// [SECTION] includes
// [SECTION] defines
// [SECTION] forward declarations & basic types
// [SECTION] internal api
// [SECTION] internal structs
// [SECTION] public api implementations
// [SECTION] internal api implementation
*/