Files
UwUGL/STYLEGUIDE.md

5.7 KiB

UwUGL Styleguide

This document describes the coding conventions used in UwUGL, inferred from the existing codebase. It prioritizes readability and simplicity for a small graphics library.


1. File Organization

  • Single monolithic header: uwugl.h is the public entry point and includes all implementation files.
  • Header-like .cpp files: Every implementation file begins with #pragma once and is designed to be #included directly by uwugl.h (or by other .cpp files). There are no traditional separate .h/.cpp pairs.
  • No separate headers for internal modules: Classes and structs are declared and defined directly in .cpp files.
  • Exception: shaders/shaders.h is a small aggregator file that includes the shader .cpp files.
  • Directory layout:
    • primatives/ — shape classes (Line, Point, Rectangle, Trapezoid, Triangle)
    • shaders/ — shader classes and base
    • waymini/ — external Wayland helper library (C)

2. Naming Conventions

  • Namespace: All library code lives in namespace UwU.
  • Classes / structs: PascalCase (Buffer, ColorShader, Rectangle, Helpers).
  • Functions / methods: camelCase (drawPixel, lerpColor, bresenham, shouldClose).
  • Member variables: lowercase with no prefix (pixels, width, x0, c).
  • Template parameters: PascalCase ending in T (ShaderT).
  • Enums: PascalCase type name; UPPER_SNAKE_CASE values (ShaderType, COLOR, HGRADIENT, VGRADIENT).
  • Constants in code: prefer lowercase; UPPER_SNAKE_CASE may be used for local compile-time-ish constants in comments or test code.
  • Filenames: lowercase and descriptive (buffer.cpp, colorshader.cpp, line.cpp).

3. Formatting

  • Indentation: 2 spaces.
  • Brace style: K&R — opening brace on the same line as the class/function/control statement.
  • Pointer/reference syntax: attach * and & to the variable name:
    • uint8_t* pixels
    • ShaderBase<ShaderT>& shader
  • Empty parameter lists: use () for default constructors, e.g., Color() {}.
  • Spacing around operators: use spaces around binary operators for readability (x + y instead of x+y).
  • Explicit return; at end of void functions: Acceptable, but not required.
  • Comments: use // for both inline and block-style comments. Keep them informal and focused on intent or known issues.

4. Includes

Include order within a file:

  1. #pragma once
  2. C/C++ standard headers (<stdint.h>, <stdio.h>, <algorithm>)
  3. Project implementation files via relative paths ("../datatypes.cpp", "../buffer.cpp")

External C library headers (e.g., "waymini/waymini.h") are included where needed.

5. Code Patterns

  • Composition over inheritance: primitives hold data; shaders are passed into draw().
  • CRTP for shaders: ShaderBase<ShaderT> uses the Curiously Recurring Template Pattern for static polymorphism.
  • Template draw methods: every primitive's draw() is templated on ShaderT and takes (Buffer buffer, ShaderBase<ShaderT>& shader).
  • Manual memory management: new uint8_t[...] in Buffer; no smart pointers.
  • C-style casts: (uint16_t)x, (uint8_t*)ptr.
  • Bounds checks: primitives guard draw() with if (x > buffer.width || y > buffer.height) {return;};.
  • Unused parameter suppression: use (void)param; to silence warnings.

6. C++ Feature Usage

Used

  • Classes and structs
  • Namespaces
  • Templates (template <class ShaderT>)
  • CRTP (Curiously Recurring Template Pattern)
  • Function overloading (constructors)
  • References
  • C-style casts
  • new / new[] for dynamic allocation
  • Raw pointers
  • Stack-allocated arrays
  • C standard headers (<stdint.h>, <stdio.h>, <stdlib.h>, <string.h>, <time.h>, <algorithm>)

Not Used but Allowed

  • Smart pointers (std::unique_ptr, std::shared_ptr)
  • Standard containers (std::vector, std::array, etc.)
  • enum class
  • Exceptions
  • std::string
  • std::chrono
  • std::function

Not Used

The following features are intentionally not used. This keeps the codebase small, predictable, and easy to reason about.

  • auto
  • Range-based for loops
  • nullptr
  • Lambda expressions
  • constexpr / consteval
  • using type aliases
  • Move semantics / rvalue references
  • Default member initializers
  • Delegating constructors
  • override / final
  • Named casts (static_cast, reinterpret_cast, etc.)
  • Structured bindings
  • Concepts / requires (C++20)
  • Virtual functions / runtime polymorphism / abstract base classes
  • Operator overloading
  • RTTI / dynamic_cast / typeid
  • <iostream> (use C-style printf/fflush)

7. Build System

  • Makefile-based.
  • C library (waymini) compiled with gcc.
  • Main example compiled with g++.
  • Flags: -Wall -Wextra -O3, plus Wayland client flags from pkg-config.

8. Known Inconsistencies and Recommendations

The codebase currently has a few inconsistencies. The following recommendations aim to improve readability without adding complexity:

  • Indentation consistency: some blocks are not aligned (e.g., line.cpp inner loop). Keep all indentation strictly at 2 spaces per level.
  • Spacing consistency: standardize on spaces around binary operators and after commas.
  • Include consistency: some primitives include ../shaders/shaders.h while rectangle.cpp also includes ../shaders/shaderbase.cpp directly. Prefer the aggregator shaders.h everywhere.
  • return; at end of void functions: acceptable, but can be omitted when it adds no clarity.
  • Bounds check style: the pattern if (...) {return;}; has a redundant semicolon. Prefer if (...) { return; }.

This guide should evolve with the project. When in doubt, favor simplicity and consistency with the existing code.